1. 基本属性の読み取り: BasicFileAttributes
ファイルやフォルダーについて語るとき、名前やサイズだけではありません。各ファイルには「パスポート」に相当する属性の集合があり、次の情報を含みます:
- 作成時刻
- 最終変更時刻
- 最終アクセス時刻
- サイズ
- アクセス権限(読み取り・書き込み・実行が可能な主体)
- 所有者情報(Unix)
- 「隠し」「読み取り専用」 などのフラグ
Java では、これらの属性を扱うための便利で強力な API がパッケージ java.nio.file.attribute に用意されています。プラットフォーム依存のコードを書く必要はありません。必要な機能は標準ライブラリに揃っています。
まずは必要なクラスをインポートします:
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;
基本属性を取得するには?
Files.readAttributes メソッドを使います:
Path path = Paths.get("example.txt");
try {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("作成: " + attrs.creationTime());
System.out.println("変更: " + attrs.lastModifiedTime());
System.out.println("最終アクセス: " + attrs.lastAccessTime());
System.out.println("サイズ: " + attrs.size());
System.out.println("ディレクトリですか? " + attrs.isDirectory());
System.out.println("通常ファイルですか? " + attrs.isRegularFile());
System.out.println("シンボリックリンクですか? " + attrs.isSymbolicLink());
} catch (IOException e) {
System.out.println("属性の読み取り中にエラー: " + e.getMessage());
}
あなたが検査官として部屋を確認しに行く状況を想像してください。扉(ファイルの存在)を見るだけでなく、住人に「いつ建てられましたか?最後にリフォームしたのはいつですか?所有者は誰ですか?」と尋ねます。
BasicFileAttributes の主なプロパティ
| プロパティ | 返り値は? |
|---|---|
|
ファイル/フォルダーの作成日時 |
|
最終変更日時 |
|
最終アクセス日時 |
|
ファイルサイズ(バイト) |
|
ディレクトリかどうか |
|
通常ファイルかどうか |
|
シンボリックリンクかどうか |
2. 拡張属性: POSIX と DOS
POSIX 属性(Linux、macOS などの Unix 系 OS)
Unix 系であれば、アクセス権・所有者・グループといった拡張情報を取得できます.
try {
PosixFileAttributes posixAttrs = Files.readAttributes(path, PosixFileAttributes.class);
System.out.println("所有者: " + posixAttrs.owner().getName());
System.out.println("グループ: " + posixAttrs.group().getName());
System.out.println("アクセス権限: " + PosixFilePermissions.toString(posixAttrs.permissions()));
} catch (UnsupportedOperationException e) {
System.out.println("この OS は POSIX 属性をサポートしていません.");
} catch (IOException e) {
System.out.println("POSIX 属性の読み取りエラー: " + e.getMessage());
}
注意: Windows ではこのコードは UnsupportedOperationException を送出します。正常な挙動です。
DOS 属性(Windows)
Windows では「読み取り専用」「隠し」「アーカイブ」「システム」フラグを扱えます:
try {
DosFileAttributes dosAttrs = Files.readAttributes(path, DosFileAttributes.class);
System.out.println("隠し: " + dosAttrs.isHidden());
System.out.println("読み取り専用: " + dosAttrs.isReadOnly());
System.out.println("システム: " + dosAttrs.isSystem());
System.out.println("アーカイブ: " + dosAttrs.isArchive());
} catch (UnsupportedOperationException e) {
System.out.println("この OS では DOS 属性はサポートされていません.");
} catch (IOException e) {
System.out.println("DOS 属性の読み取りエラー: " + e.getMessage());
}
3. ファイル属性の変更
他人のパスポートを読むのと、生年月日や姓を変えるのとは別物です!Java では(必要な権限があれば)ファイルの属性を変更できます。
最終更新時刻の変更
import java.nio.file.attribute.FileTime;
Path file = Paths.get("example.txt");
try {
FileTime newTime = FileTime.fromMillis(System.currentTimeMillis() - 24 * 60 * 60 * 1000); // 1日分引く
Files.setLastModifiedTime(file, newTime);
System.out.println("最終更新時刻を変更しました!");
} catch (IOException e) {
System.out.println("時刻の変更中にエラー: " + e.getMessage());
}
アクセス権の変更(POSIX)
Unix 系のみ!例えば、ファイルを全員実行可能にします:
try {
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-xr-x");
Files.setPosixFilePermissions(file, perms);
System.out.println("アクセス権を変更しました!");
} catch (UnsupportedOperationException e) {
System.out.println("この OS は POSIX 権限をサポートしていません.");
} catch (IOException e) {
System.out.println("権限変更中にエラー: " + e.getMessage());
}
文字列の説明 "rwxr-xr-x":
- r — read(読み取り)
- w — write(書き込み)
- x — execute(実行)
- 3 文字ずつのブロックで、最初が所有者、次がグループ、最後がその他。
隠し/読み取り専用フラグの変更(DOS 属性、Windows)
ファイルを隠しにする:
try {
Files.setAttribute(file, "dos:hidden", true);
System.out.println("ファイルを非表示にしました(Windows)!");
} catch (UnsupportedOperationException e) {
System.out.println("この OS では DOS 属性はサポートされていません.");
} catch (IOException e) {
System.out.println("属性変更中にエラー: " + e.getMessage());
}
ファイルを「読み取り専用」にする:
try {
Files.setAttribute(file, "dos:readonly", true);
System.out.println("ファイルは読み取り専用になりました(Windows)!");
} catch (UnsupportedOperationException e) {
System.out.println("この OS では DOS 属性はサポートされていません.");
} catch (IOException e) {
System.out.println("属性変更中にエラー: " + e.getMessage());
}
4. アクセス権の確認
読み取り・書き込み・実行が可能かを素早く確認したいことがあります:
Path file = Paths.get("example.txt");
System.out.println("読み取り可能: " + Files.isReadable(file));
System.out.println("書き込み可能: " + Files.isWritable(file));
System.out.println("実行可能: " + Files.isExecutable(file));
これはすべてのプラットフォームで同様に動作しますが、実際の挙動は OS やセキュリティ設定に依存します。
5. 実践: ファイルの詳細情報を出力する
指定したパスのファイルについて可能な限り詳細を表示し、いくつかの属性を変更してみるミニプログラムを書きます。
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.Set;
import java.io.IOException;
public class FileAttributesDemo {
public static void main(String[] args) throws IOException {
Path path = Paths.get("example.txt");
if (!Files.exists(path)) {
System.out.println("ファイルが見つかりません!");
return;
}
// 基本属性
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("名前: " + path.getFileName());
System.out.println("パス: " + path.toAbsolutePath());
System.out.println("サイズ: " + attrs.size() + " バイト");
System.out.println("作成: " + attrs.creationTime());
System.out.println("変更: " + attrs.lastModifiedTime());
System.out.println("最終アクセス: " + attrs.lastAccessTime());
System.out.println("ディレクトリですか? " + attrs.isDirectory());
System.out.println("通常ファイルですか? " + attrs.isRegularFile());
// アクセス権の確認
System.out.println("読み取り可能: " + Files.isReadable(path));
System.out.println("書き込み可能: " + Files.isWritable(path));
System.out.println("実行可能: " + Files.isExecutable(path));
// 更新時刻を変更してみる
FileTime now = FileTime.fromMillis(System.currentTimeMillis());
Files.setLastModifiedTime(path, now);
System.out.println("最終更新時刻を更新しました!");
// (サポートされていれば)ファイルを隠しにしてみる
try {
Files.setAttribute(path, "dos:hidden", true);
System.out.println("(OS がサポートしていれば)ファイルを非表示にしました。");
} catch (UnsupportedOperationException e) {
System.out.println("この OS は隠しファイルをサポートしていません。");
}
// (サポートされていれば)POSIX 権限を表示してみる
try {
PosixFileAttributes posixAttrs = Files.readAttributes(path, PosixFileAttributes.class);
System.out.println("所有者: " + posixAttrs.owner().getName());
System.out.println("アクセス権限: " + PosixFilePermissions.toString(posixAttrs.permissions()));
} catch (UnsupportedOperationException e) {
System.out.println("この OS は POSIX 属性をサポートしていません。");
}
}
}
6. 役立つポイント
クロスプラットフォームの違いとヒント
- すべての OS で全属性が使えるわけではありません! Windows には POSIX 権限がなく、Linux には DOS 属性がありません。
- 必ず try-catch を使いましょう! メソッドは UnsupportedOperationException や IOException を送出する可能性があります。
- アクセス権は常に「rwx」だけとは限りません! Windows では権限モデルが異なり、「読み取り専用」は OS のセキュリティポリシーで設定されることがあります。
- 隠しファイルの概念も相対的です。 Unix では名前がドットで始まる(.hidden)と隠し、Windows では属性 dos:hidden が設定されると隠しになります。
表: どの属性がどこで利用可能か
| 属性 | Windows (dos:*) | Linux/macOS (posix:*) |
|---|---|---|
| 作成時刻 | + | + |
| 最終変更時刻 | + | + |
| 最終アクセス時刻 | + | + |
| 隠しファイル | + | 先頭ドット名のみ |
| 読み取り専用 | + | + |
| アクセス権(rwx) | - | + |
| 所有者・グループ | - | + |
| アーカイブ・システム | + | - |
7. ファイル属性を扱う際の典型的なミス
エラー1: Windows で POSIX 属性を読み書きしようとする。 Windows では UnsupportedOperationException を受け取ります。クロスプラットフォームなコードでは必ずこの例外を処理してください。
エラー2: 別のプロセスが開いているファイルの最終更新時刻を変更する。 システムによってはファイルがロックされ、操作は失敗します。
エラー3: 「ファイルを隠す」操作がすべての OS で同じに動くと期待する。 Unix ではファイル名がドットで始まる(.gitignore)と隠し、Windows では属性 dos:hidden が設定されていると隠しになります。この違いを混同しないでください。
エラー4: 操作の前にファイルの存在を確認しない。 ファイルがない場合、属性の取得や変更を試みると NoSuchFileException になります。
エラー5: 権限チェックを怠る。 ユーザーに属性を変更する権限がないと操作は失敗します。変更の前に Files.isWritable(path) を確認しましょう。
GO TO FULL VERSION