NIO2ファイル属性APIの手引き

NIO2ファイル属性APIのガイド

1. 概要

この記事では、Java 7 NIO.2ファイルシステムAPIの高度な機能の1つ、特にファイル属性APIについて説明します。

これらの基本的な部分を最初に深く掘り下げたい場合は、以前にFilePath APIsについて説明しました。

ファイルシステム操作の処理に必要なすべてのファイルは、java.nio.file packageにまとめられています。

import java.nio.file.*;

2. 基本的なファイル属性

すべての必須およびオプションの表示可能なファイル属性を格納する、BasicFileAttributeViewによって提供されるすべてのファイルシステムに共通の基本属性の高レベルのビューから始めましょう。

HOMEへのパスを作成し、その基本属性ビューを取得することで、現在のマシン上のユーザーのホームロケーションの基本属性を調べることができます。

String HOME = System.getProperty("user.home");
Path home = Paths.get(HOME);
BasicFileAttributeView basicView =
  Files.getFileAttributeView(home, BasicFileAttributeView.class);

上記の手順の後、1回の一括操作でポイントされたパスのすべての属性を読み取ることができます。

BasicFileAttributes basicAttribs = basicView.readAttributes();

私たちは現在、特に条件文でアプリケーションで実際に使用できるさまざまな共通属性を調査する立場にあります。

基本属性コンテナからファイルのサイズを照会できます。

@Test
public void givenPath_whenGetsFileSize_thenCorrect() {
    long size = basicAttribs.size();
    assertTrue(size > 0);
}

ディレクトリかどうかも確認できます。

@Test
public void givenPath_whenChecksIfDirectory_thenCorrect() {
    boolean isDir = basicAttribs.isDirectory();
    assertTrue(isDir);
}

または通常のファイル:

@Test
public void givenPath_whenChecksIfFile_thenCorrect() {
    boolean isFile = basicAttribs.isRegularFile();
    assertFalse(isFile);
}

Java NIO.2では、ファイルシステム内のシンボリックリンクまたはソフトリンクを処理できるようになりました。 これらは、通常ショートカットと呼ばれるファイルまたはディレクトリです。

ファイルがシンボリックリンクかどうかを確認するには:

@Test
public void givenPath_whenChecksIfSymLink_thenCorrect() {
    boolean isSymLink = basicAttribs.isSymbolicLink();
    assertFalse(isSymLink);
}

まれに、isOther APIを呼び出して、ファイルが通常のファイル、ディレクトリ、またはシンボリックリンクの一般的なカテゴリのいずれにも属していないかどうかを確認できます。

@Test
public void givenPath_whenChecksIfOther_thenCorrect() {
    boolean isOther = basicAttribs.isOther();
    assertFalse(isOther);
}

ファイルが作成された時刻を取得するには:

FileTime created = basicAttribs.creationTime();

最終変更時刻を取得するには:

FileTime modified = basicAttribs.lastModifiedTime();

最後のアクセス時間を取得するには:

FileTime accessed = basicAttribs.lastAccessTime();

上記のすべての例は、FileTimeオブジェクトを返します。 これは単なるタイムスタンプよりも使いやすい抽象化です。

たとえば、2つのファイル時間を簡単に比較して、どちらのイベントが前後に発生したかを知ることができます。

@Test
public void givenFileTimes_whenComparesThem_ThenCorrect() {
    FileTime created = basicAttribs.creationTime();
    FileTime modified = basicAttribs.lastModifiedTime();
    FileTime accessed = basicAttribs.lastAccessTime();

    assertTrue(0 >= created.compareTo(accessed));
    assertTrue(0 <= modified.compareTo(created));
    assertTrue(0 == created.compareTo(created));
}

compareTo APIは、Javaの他の同等のものと同じように機能します。 呼び出されているオブジェクトが引数よりも小さい場合は、負の値を返します。私たちの場合、作成時間は、最初のアサーションのように、アクセス時間の前に必ず来ます。

2番目のアサーションでは、変更は作成イベントの後にのみ行えるため、正の整数値を取得します。 そして最後に、比較される時間が等しい場合、0を返します。

FileTimeオブジェクトがある場合、必要に応じて他のほとんどのユニットに変換できます。日、時間、分、秒、ミリ秒など。 これを行うには、適切なAPIを呼び出します。

accessed.to(TimeUnit.SECONDS);
accessed.to(TimeUnit.HOURS);
accessed.toMillis();

toString APIを呼び出すことで、人間が読める形式のファイル時間を印刷することもできます。

accessed.toString();

ISO時間形式で有用なものを出力します:

2016-11-24T07:52:53.376Z

ビューのsetTimes(modified, accessed, created) APIを呼び出すことにより、ビューの時間属性を変更することもできます。 変更したい場所に新しいFileTimeオブジェクトを渡すか、変更したくない場所にnullを渡します。

最終アクセス時刻を1分後まで変更するには、次の手順に従います。

FileTime newAccessTime = FileTime.fromMillis(
  basicAttribs.lastAccessTime().toMillis() + 60000);
basicView.setTimes(null, newAccessTime , null);

この変更は、マシン上で実行され、ファイルシステムを使用している他のアプリケーションから見られるように、実際のファイルに残ります。

3. ファイルスペース属性

Windows、Linux、またはMacでmy computerを開くと、通常、ストレージドライブに関するスペース情報のグラフィック分析が表示されます。

Java NIO.2は、この種の高レベル機能を非常に簡単にします。 基本的なファイルシステムとやり取りしてこの情報を取得しますが、単純なAPIを呼び出すだけです。

FileStoreクラスを使用して、ストレージドライブを検査し、サイズ、使用されているスペースの量、未使用の量などの重要な情報を取得できます。

ファイルシステム内の任意のファイルの場所のFileStoreインスタンスを取得するには、FilesクラスのgetFileStoreAPIを使用します。

Path file = Paths.get("file");
FileStore store = Files.getFileStore(file);

このFileStoreインスタンスは、ファイル自体ではなく、指定されたファイルが配置されているファイルストアを具体的に表します。 合計スペースを取得するには:

long total = store.getTotalSpace();

使用済みスペースを取得するには:

long used = store.getTotalSpace() - store.getUnallocatedSpace();

次のアプローチよりこのアプローチに従う可能性は低くなります。

より一般的には、すべてのファイルストアに関するストレージ情報に関する情報を取得する可能性があります。 プログラムでmy computer'sグラフィックドライブスペース情報をエミュレートするには、FileSystemクラスを使用してファイルストアを列挙します。

Iterable fileStores = FileSystems.getDefault().getFileStores();

その後、返された値をループ処理し、グラフィカルユーザーインターフェイスの更新など、情報を使用して必要な処理を実行できます。

for (FileStore fileStore : fileStores) {
    long totalSpace = fileStore.getTotalSpace();
    long unAllocated = fileStore.getUnallocatedSpace();
    long usable = fileStore.getUsableSpace();
}

返される値はすべてバイト単位であることに注意してください。 適切な単位に変換するだけでなく、基本的な計算を使用して使用済みスペースなどの他の情報を計算することもできます。

The difference between unallocated space and usable spaceはJVMにアクセスできます。

使用可能スペースは、JVMで使用可能なスペースであり、未割り当てスペースは、基礎となるファイルシステムから見た使用可能なスペースです。 したがって、使用可能なスペースは未割り当てスペースよりも小さい場合があります。

4. ファイル所有者の属性

ファイルの所有権情報を検査するには、FileOwnerAttributeViewインターフェイスを使用します。 所有権情報の高レベルのビューを提供します。

次のようにFileOwnerAttributeViewオブジェクトを作成できます。

Path path = Paths.get(HOME);
FileOwnerAttributeView ownerView = Files.getFileAttributeView(
  attribPath, FileOwnerAttributeView.class);

上記のビューからファイルの所有者を取得するには:

UserPrincipal owner = ownerView.getOwner();

上記のオブジェクトでは、他の任意の目的で所有者の名前を取得することを除いて、プログラムで実行できることはほとんどありません。

String ownerName = owner.toString();

5. ユーザー定義のファイル属性

ファイルシステムで定義されたファイル属性がニーズに十分でないシナリオがあります。 このような場合に遭遇し、ファイルに独自の属性を設定する必要がある場合は、UserDefinedFileAttributeViewインターフェイスが役立ちます。

Path path = Paths.get("somefile");
UserDefinedFileAttributeView userDefView = Files.getFileAttributeView(
  attribPath, UserDefinedFileAttributeView.class);

上記のビューで表されるファイルに対してすでに定義されているユーザー定義属性のリストを取得するには:

List attribList = userDefView.list();

ファイルにユーザー定義の属性を設定するには、次のイディオムを使用します。

String name = "attrName";
String value = "attrValue";
userDefView.write(name, Charset.defaultCharset().encode(value));

ユーザー定義の属性にアクセスする必要がある場合、ビューによって返された属性リストをループし、このイディオムを使用してそれらを検査できます。

ByteBuffer attrValue = ByteBuffer.allocate(userView.size(attrName));
userDefView.read(attribName, attribValue);
attrValue.flip();
String attrValue = Charset.defaultCharset().decode(attrValue).toString();

ファイルからユーザー定義の属性を削除するには、単にビューの削除APIを呼び出します。

userDefView.delete(attrName);

6. 結論

この記事では、Java 7 NIO.2ファイルシステムAPI、特にファイル属性APIで使用できる、あまり一般的に使用されない機能のいくつかを調べました。

この記事で使用されている例の完全なソースコードは、Github projectで入手できます。