Java Files Open Options – Java文件打开选项

最后修改: 2020年 8月 10日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’re going to focus on the standard open options available for files in Java.

在本教程中,我们将重点讨论Java中文件可用的标准打开选项。

We’ll explore the StandardOpenOption enum that implements the OpenOption interface and that defines these standard open options.

我们将探索实现OpenOption接口的StandardOpenOption枚举,它定义了这些标准的开放选项。

2. The OpenOption Parameter

2.OpenOption 参数

In Java, we can work with files using the NIO2 API, which contains several utility methods. Some of these methods use an optional OpenOption parameter that configures how to open or create a file. In addition, this parameter will have a default value if not set, which can be different for each of these methods.

在Java中,我们可以使用NIO2 API来处理文件,它包含几个实用方法。其中一些方法使用一个可选的OpenOption参数来配置如何打开或创建一个文件。此外,如果没有设置,这个参数将有一个默认值,这些方法中的每一个都可能是不同的。

The StandardOpenOption enum type defines the standard options and implements the OpenOption interface.

StandardOpenOption枚举类型定义了标准选项并实现了OpenOption接口。

Here’s the list of supported options we can use with the StandardOpenOptions enum:

以下是我们可以使用StandardOpenOptions枚举的支持选项列表:

  • WRITE: opens the file for write access
  • APPEND: appends some data to the file
  • TRUNCATE_EXISTING: truncates the file
  • CREATE_NEW: creates a new file and throws an exception if the file already exists
  • CREATE: opens the file if it exists or creates a new file if it does not
  • DELETE_ON_CLOSE: deletes the file after closing the stream
  • SPARSE: the newly created file will be sparse
  • SYNC: preserves the content and the metadata of the file synchronized
  • DSYNC: preserves only the content of the file synchronized

In the next sections, we’ll see examples of how to use each of these options.

在接下来的章节中,我们将看到如何使用这些选项的例子。

To avoid any confusion on the file path, let’s get a handle on the home directory of the user, which will be valid across all operating systems:

为了避免文件路径上的混乱,让我们掌握用户的主目录,这在所有的操作系统中都是有效的。

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

3. Opening a File for Reading and Writing

3.打开一个文件进行读和写

First, if we want to create a new file if it does not exist we can use the option CREATE:

首先,如果我们想创建一个不存在的新文件,我们可以使用选项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));
}

We can also use the option CREATE_NEW, which will create a new file if it does not exist. However, it will throw an exception if the file already exists.

我们还可以使用选项CREATE_NEW,它将创建一个不存在的新文件。 然而,如果文件已经存在,它将抛出一个异常。

Secondly, if we want to open the file for reading we can use the newInputStream(Path, OpenOption...) method. This method opens the file for reading and returns an input stream:

其次,如果我们想打开文件进行阅读,我们可以使用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));
        }
    }
}

Notice how we didn’t use the option READ because it’s used by default by the method newInputStream.

注意我们没有使用选项READ,因为方法newInputStream默认使用它。

Third, we can create a file, append to a file, or write to a file by using the newOutputStream(Path, OpenOption...) method. This method opens or creates a file for writing and returns an OutputStream.

第三,我们可以通过使用newOutputStream(Path, OpenOption.…)方法来创建一个文件,追加到一个文件,或者写到一个文件。这个方法可以打开或创建一个文件进行写入,并返回一个OutputStream

The API will create a new file if we don’t specify the open options, and the file does not exist. However, if the file exists, it will be truncated. This option is similar to calling the method with the CREATE and TRUNCATE_EXISTING options.

如果我们不指定打开选项,并且文件不存在,API将创建一个新的文件。然而,如果文件存在,它将被截断。这个选项类似于用CREATETRUNCATE_EXISTING选项调用该方法。

Let’s open an existing file and append some data:

让我们打开一个现有的文件并添加一些数据。

@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. Creating a SPARSE File

4.创建一个SPARSE文件

We can tell the file system that the newly created file should be sparse (files containing empty spaces that will not be written to disk).

我们可以告诉文件系统,新创建的文件应该是稀疏的(包含空位的文件,不会被写入磁盘)。

For this, we should use the option SPARSE with the CREATE_NEW option. However, this option will be ignored if the file system does not support sparse files.

为此,我们应该使用选项SPARSECREATE_NEW选项。然而,如果文件系统不支持稀疏文件,该选项将被忽略

Let’s create a sparse file:

让我们创建一个稀疏的文件。

@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. Keeping the File Synchronized

5.保持文件的同步性

The StandardOpenOptions enum has SYNC and DSYNC options. These options require that data is written to the file synchronously in the storage. In other words, these will guarantee that the data is not lost in the event of a system crash.

StandardOpenOptions枚举有SYNCDSYNC选项。这些选项要求在存储中同步地将数据写入文件。换句话说,这些将保证在系统崩溃的情况下,数据不会丢失

Let’s append some data to our file and use the option SYNC:

让我们把一些数据追加到我们的文件中,并使用选项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);
}

The difference between SYNC and DSYNC is that SYNC stores the content and the metadata of the file synchronously in the storage, while DSYNC stores only the contents of the file synchronously in the storage.

SYNCDSYNC之间的区别是,SYNC在存储中同步存储文件的内容和元数据,而DSYNC只在存储中同步存储文件的内容

6. Deleting the File After Closing the Stream

6.关闭数据流后删除文件

The StandardOpenOptions enum also offers a useful option that gives us the ability to destroy the file after closing the stream. This useful if we want to create a temporary file.

StandardOpenOptions枚举还提供了一个有用的选项,使我们能够在关闭流之后销毁文件。如果我们想创建一个临时文件,这一点很有用。

Let’s append some data to our file, and use the option DELETE_ON_CLOSE:

让我们在我们的文件中追加一些数据,并使用选项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. Conclusion

7.结语

In this tutorial, we covered the available options to open files in Java using the new file system API (NIO2) that was shipped as a part of Java 7.

在本教程中,我们介绍了在Java中使用新的文件系统API(NIO2)打开文件的可用选项,该API是作为Java 7的一部分提供的。

As usual, the source code with all the examples in the tutorial can be found over on Github.

像往常一样,可以在Github上找到包含本教程中所有示例的源代码