1. 概要

このチュートリアルでは、Javaのファイルで使用できる標準のオープンオプションに焦点を当てます。

OpenOption インターフェイスを実装し、これらの標準オープンオプションを定義するStandardOpenOption列挙型について説明します。

2. OpenOptionパラメーター

Javaでは、いくつかのユーティリティメソッドを含むNIO2APIを使用してファイルを操作できます。 これらのメソッドの一部は、ファイルを開く方法または作成する方法を構成するオプションのOpenOptionパラメーターを使用します。 さらに、このパラメーターは、設定されていない場合はデフォルト値になります。これは、これらのメソッドごとに異なる可能性があります。

StandardOpenOption 列挙型は、標準オプションを定義し、OpenOptionインターフェイスを実装します。

StandardOpenOptions列挙型で使用できるサポートされているオプションのリストは次のとおりです。

  • WRITE :書き込みアクセス用にファイルを開きます
  • APPEND :ファイルにデータを追加します
  • TRUNCATE_EXISTING :ファイルを切り捨てます
  • CREATE_NEW :新しいファイルを作成し、ファイルがすでに存在する場合は例外をスローします
  • CREATE :ファイルが存在する場合はファイルを開き、存在しない場合は新しいファイルを作成します
  • DELETE_ON_CLOSE :ストリームを閉じた後にファイルを削除します
  • SPARSE :新しく作成されたファイルはまばらになります
  • SYNC :同期されたファイルのコンテンツとメタデータを保持します
  • DSYNC :同期されたファイルのコンテンツのみを保持します

次のセクションでは、これらの各オプションの使用方法の例を示します。

ファイルパスの混乱を避けるために、ユーザーのホームディレクトリのハンドルを取得しましょう。これはすべてのオペレーティングシステムで有効です。

private static String HOME = System.getProperty("user.home");

3. 読み取りと書き込みのためにファイルを開く

まず、が存在しない場合に新しいファイルを作成する場合は、オプションCREATEを使用できます。

@Test
public void givenExistingPath_whenCreateNewFile_thenCorrect() throws IOException {
    assertFalse(Files.exists(Paths.get(HOME, "newfile.txt")));
    Files.write(path, DUMMY_TEXT.getBytes(), StandardOpenOption.CREATE);
    assertTrue(Files.exists(path));
}

オプションCREATE_NEWを使用することもできます。これにより、新しいファイルが存在しない場合は作成されます。 ただし、ファイルが既に存在する場合は例外がスローされます。

次に、でファイルを開いて読み取りたい場合は、newInputStream(Path、OpenOption。 ..)メソッドを使用できます。 このメソッドは、読み取り用にファイルを開き、入力ストリームを返します。

@Test
public void givenExistingPath_whenReadExistingFile_thenCorrect() throws IOException {
    Path path = Paths.get(HOME, DUMMY_FILE_NAME);

    try (InputStream in = Files.newInputStream(path); BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
        String line;
        while ((line = reader.readLine()) != null) {
            assertThat(line, CoreMatchers.containsString(DUMMY_TEXT));
        }
    }
}

オプションREADは、デフォルトでメソッドnewInputStream によって使用されるため、使用しなかったことに注意してください。

第3に、 newOutputStream(Path、OpenOption。 ..)メソッドを使用して、ファイルの作成、ファイルへの追加、またはファイルへの書き込みを行うことができます。 このメソッドは、書き込み用のファイルを開くか作成し、OutputStreamを返します。

開くオプションを指定せず、ファイルが存在しない場合、APIは新しいファイルを作成します。 ただし、ファイルが存在する場合は切り捨てられます。 このオプションは、CREATEおよびTRUNCATE_EXISTINGオプションを使用してメソッドを呼び出すのと似ています。

既存のファイルを開いて、いくつかのデータを追加しましょう。

@Test
public void givenExistingPath_whenWriteToExistingFile_thenCorrect() throws IOException {
    Path path = Paths.get(HOME, DUMMY_FILE_NAME);

    try (OutputStream out = Files.newOutputStream(path, StandardOpenOption.APPEND, StandardOpenOption.WRITE)) {
        out.write(ANOTHER_DUMMY_TEXT.getBytes());
    }
}

4. SPARSEファイルの作成

新しく作成されたファイルはスパース(ディスクに書き込まれない空のスペースを含むファイル)である必要があることをファイルシステムに伝えることができます。

このためには、オプションSPARSECREATE_NEWオプションとともに使用する必要があります。 ただし、ファイルシステムがスパースファイルをサポートしていない場合、このオプションは無視されます。

スパースファイルを作成しましょう:

@Test
public void givenExistingPath_whenCreateSparseFile_thenCorrect() throws IOException {
    Path path = Paths.get(HOME, "sparse.txt");
    Files.write(path, DUMMY_TEXT.getBytes(), StandardOpenOption.CREATE_NEW, StandardOpenOption.SPARSE);
}

5. ファイルの同期を維持する

StandardOpenOptions列挙型にはSYNCおよびDSYNCオプションがあります。 これらのオプションでは、データがストレージ内のファイルに同期的に書き込まれる必要があります。 つまり、これらは、システムクラッシュの場合にデータが失われないことを保証します。

ファイルにデータを追加して、オプションSYNCを使用してみましょう。

@Test
public void givenExistingPath_whenWriteAndSync_thenCorrect() throws IOException {
    Path path = Paths.get(HOME, DUMMY_FILE_NAME);
    Files.write(path, ANOTHER_DUMMY_TEXT.getBytes(), StandardOpenOption.APPEND, StandardOpenOption.WRITE, StandardOpenOption.SYNC);
}

SYNCDSYNCの違いは、 SYNC はファイルのコンテンツとメタデータを同期的にストレージに保存し、は] DSYNCは、ファイルの内容のみを同期的にストレージに保存します。

6. ストリームを閉じた後のファイルの削除

StandardOpenOptions 列挙型は、ストリームを閉じた後にファイルを破棄する機能を提供する便利なオプションも提供します。 これは一時ファイルを作成する場合に便利です。

ファイルにデータを追加して、オプションDELETE_ON_CLOSEを使用してみましょう。

@Test
public void givenExistingPath_whenDeleteOnClose_thenCorrect() throws IOException {
    Path path = Paths.get(HOME, EXISTING_FILE_NAME);
    assertTrue(Files.exists(path)); // file was already created and exists

    try (OutputStream out = Files.newOutputStream(path, StandardOpenOption.APPEND, 
      StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE)) {
        out.write(ANOTHER_DUMMY_TEXT.getBytes());
    }

    assertFalse(Files.exists(path)); // file is deleted
}

7. 結論

このチュートリアルでは、Java 7の一部として出荷された新しいファイルシステムAPI(NIO2)を使用してJavaでファイルを開くために使用できるオプションについて説明しました。

いつものように、チュートリアルのすべての例を含むソースコードは、Githubにあります。