Documentation

The Java™ Tutorials
Hide TOC
Reading, Writing, and Creating Files读取、写入和创建文件
Trail: Essential Java Classes
Lesson: Basic I/O
Section: File I/O (Featuring NIO.2)

Reading, Writing, and Creating Files读取、写入和创建文件

This page discusses the details of reading, writing, creating, and opening files. 本页讨论读取、写入、创建和打开文件的详细信息。There are a wide array of file I/O methods to choose from. 有许多文件I/O方法可供选择。To help make sense of the API, the following diagram arranges the file I/O methods by complexity.为了帮助理解API,下图按复杂性排列了文件I/O方法。

Line drawing with file I/O methods arranged from least complex (on the left) to most complex (on the right).

File I/O Methods Arranged from Less Complex to More Complex文件I/O方法从较不复杂到较复杂

On the far left of the diagram are the utility methods readAllBytes, readAllLines, and the write methods, designed for simple, common cases. 图的最左边是实用程序方法readAllBytesreadAllLineswrite方法,它们是为简单、常见的情况设计的。To the right of those are the methods used to iterate over a stream or lines of text, such as newBufferedReader, newBufferedWriter, then newInputStream and newOutputStream. 在这些方法的右边是用于迭代一个或多个文本行的方法,例如newBufferedWriternewBufferedWriternewInputStreamnewOutputStreamThese methods are interoperable with the java.io package. 这些方法可以与java.io包进行互操作。To the right of those are the methods for dealing with ByteChannels, SeekableByteChannels, and ByteBuffers, such as the newByteChannel method. 右边是处理ByteChannelsSeekableByteChannelsByteBuffers的方法,如newByteChannel方法。Finally, on the far right are the methods that use FileChannel for advanced applications needing file locking or memory-mapped I/O.最后,最右边是使用FileChannel的方法,用于需要文件锁定或内存映射I/O的高级应用程序。


Note: The methods for creating a new file enable you to specify an optional set of initial attributes for the file. 创建新文件的方法使您能够为文件指定一组可选的初始属性。For example, on a file system that supports the POSIX set of standards (such as UNIX), you can specify a file owner, group owner, or file permissions at the time the file is created. 例如,在支持POSIX标准集的文件系统(如UNIX)上,可以在创建文件时指定文件所有者、组所有者或文件权限。The Managing Metadata page explains file attributes, and how to access and set them. 管理元数据页面解释了文件属性以及如何访问和设置它们。

This page has the following topics:此页面包含以下主题:


The OpenOptions ParameterOpenOptions参数

Several of the methods in this section take an optional OpenOptions parameter. 本节中的几个方法采用可选的OpenOptions参数。This parameter is optional and the API tells you what the default behavior is for the method when none is specified.此参数是可选的,API会告诉您在未指定任何参数时方法的默认行为。

The following StandardOpenOptions enums are supported:支持以下StandardOpenOptions枚举:


Commonly Used Methods for Small Files小文件的常用方法

Reading All Bytes or Lines from a File从文件中读取所有字节或行

If you have a small-ish file and you would like to read its entire contents in one pass, you can use the readAllBytes(Path) or readAllLines(Path, Charset) method. 如果您有一个小ish文件,并且希望一次性读取其全部内容,则可以使用readAllBytes(Path)方法或readAllLines(Path, Charset)方法。These methods take care of most of the work for you, such as opening and closing the stream, but are not intended for handling large files. 这些方法负责您的大部分工作,例如打开和关闭流,但不用于处理大型文件。The following code shows how to use the readAllBytes method:以下代码显示了如何使用readAllBytes方法:

Path file = ...;
byte[] fileArray;
fileArray = Files.readAllBytes(file);

Writing All Bytes or Lines to a File将所有字节或行写入文件

You can use one of the write methods to write bytes, or lines, to a file.可以使用其中一种写入方法将字节或行写入文件。

The following code snippet shows how to use a write method.下面的代码片段显示了如何使用write方法。

Path file = ...;
byte[] buf = ...;
Files.write(file, buf);

Buffered I/O Methods for Text Files文本文件的缓冲I/O方法

The java.nio.file package supports channel I/O, which moves data in buffers, bypassing some of the layers that can bottleneck stream I/O.java.nio.file包支持通道I/O,它在缓冲区中移动数据,绕过一些可能导致流I/O瓶颈的层。

Reading a File by Using Buffered Stream I/O使用缓冲流I/O读取文件

The newBufferedReader(Path, Charset) method opens a file for reading, returning a BufferedReader that can be used to read text from a file in an efficient manner.newBufferedReader(Path, Charset)方法打开一个文件进行读取,返回一个BufferedReader,可用于高效地从文件中读取文本。

The following code snippet shows how to use the newBufferedReader method to read from a file. 下面的代码片段显示了如何使用newBufferedReader方法读取文件。The file is encoded in "US-ASCII."该文件以“US-ASCII”编码。

Charset charset = Charset.forName("US-ASCII");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
    String line = null;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException x) {
    System.err.format("IOException: %s%n", x);
}

Writing a File by Using Buffered Stream I/O使用缓冲流I/O写入文件

You can use the newBufferedWriter(Path, Charset, OpenOption...) method to write to a file using a BufferedWriter.您可以使用newBufferedWriter(Path, Charset, OpenOption...)方法使用BufferedWriter写入文件。

The following code snippet shows how to create a file encoded in "US-ASCII" using this method:以下代码段显示了如何使用此方法创建以“US-ASCII”编码的文件:

Charset charset = Charset.forName("US-ASCII");
String s = ...;
try (BufferedWriter writer = Files.newBufferedWriter(file, charset)) {
    writer.write(s, 0, s.length());
} catch (IOException x) {
    System.err.format("IOException: %s%n", x);
}

Methods for Unbuffered Streams and Interoperable with java.io APIs用于无缓冲流和可与java.io API互操作的方法

Reading a File by Using Stream I/O使用流I/O读取文件

To open a file for reading, you can use the newInputStream(Path, OpenOption...) method. 要打开文件进行读取,可以使用newInputStream(Path, OpenOption...)方法。This method returns an unbuffered input stream for reading bytes from the file.此方法返回一个无缓冲的输入流,用于从文件中读取字节。

Path file = ...;
try (InputStream in = Files.newInputStream(file);
    BufferedReader reader =
      new BufferedReader(new InputStreamReader(in))) {
    String line = null;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException x) {
    System.err.println(x);
}

Creating and Writing a File by Using Stream I/O使用流I/O创建和写入文件

You can create a file, append to a file, or write to a file by using the newOutputStream(Path, OpenOption...) method. 您可以使用newOutputStream(Path, OpenOption...)方法创建文件、附加到文件或写入文件。This method opens or creates a file for writing bytes and returns an unbuffered output stream.此方法打开或创建用于写入字节的文件,并返回未缓冲的输出流。

The method takes an optional OpenOption parameter. 该方法采用可选的OpenOption参数。If no open options are specified, and the file does not exist, a new file is created. 如果未指定打开选项,且文件不存在,则会创建一个新文件。If the file exists, it is truncated. 如果文件存在,它将被截断。This option is equivalent to invoking the method with the CREATE and TRUNCATE_EXISTING options.此选项相当于使用CREATETRUNCATE_EXISTING选项调用该方法。

The following example opens a log file. 下面的示例打开一个日志文件。If the file does not exist, it is created. If the file exists, it is opened for appending.如果文件不存在,则创建该文件。如果文件存在,则打开该文件进行附加。

import static java.nio.file.StandardOpenOption.*;
import java.nio.file.*;
import java.io.*;

public class LogFileTest {

  public static void main(String[] args) {

    // Convert the string to a
    // byte array.
    String s = "Hello World! ";
    byte data[] = s.getBytes();
    Path p = Paths.get("./logfile.txt");

    try (OutputStream out = new BufferedOutputStream(
      Files.newOutputStream(p, CREATE, APPEND))) {
      out.write(data, 0, data.length);
    } catch (IOException x) {
      System.err.println(x);
    }
  }
}

Methods for Channels and ByteBuffers通道和ByteBuffers的方法

Reading and Writing Files by Using Channel I/O使用通道I/O读写文件

While stream I/O reads a character at a time, channel I/O reads a buffer at a time. 当流I/O一次读取一个字符时,通道I/O一次读取一个缓冲区。The ByteChannel interface provides basic read and write functionality. ByteChannel接口提供基本的读写功能。A SeekableByteChannel is a ByteChannel that has the capability to maintain a position in the channel and to change that position. SeekableByteChannel是一种ByteChannel,能够在通道中保持位置并更改该位置。A SeekableByteChannel also supports truncating the file associated with the channel and querying the file for its size.SeekableByteChannel还支持截断与通道关联的文件并查询文件的大小。

The capability to move to different points in the file and then read from or write to that location makes random access of a file possible. 能够移动到文件中的不同点,然后从该位置读取或写入,从而可以对文件进行随机访问。See Random Access Files for more information.有关详细信息,请参阅随机访问文件

There are two methods for reading and writing channel I/O.有两种读取和写入通道I/O的方法。


Note: The newByteChannel methods return an instance of a SeekableByteChannel. newByteChannel方法返回seekableytechannel的实例。With a default file system, you can cast this seekable byte channel to a FileChannel providing access to more advanced features such mapping a region of the file directly into memory for faster access, locking a region of the file so other processes cannot access it, or reading and writing bytes from an absolute position without affecting the channel's current position. 使用默认文件系统,您可以将此可查找字节通道强制转换为FileChannel,以提供对更高级功能的访问,例如将文件区域直接映射到内存中以实现更快的访问,锁定文件区域以使其他进程无法访问它,或者从绝对位置读取和写入字节,而不影响通道的当前位置。

Both newByteChannel methods enable you to specify a list of OpenOption options. <两种newByteChannel方法都允许您指定OpenOption选项列表。/ins>The same open options used by the newOutputStream methods are supported, in addition to one more option: READ is required because the SeekableByteChannel supports both reading and writing.newOutputStream方法使用的相同打开选项也受支持,此外还有一个选项:READ是必需的,因为SeekableByteChannel同时支持读取和写入。

Specifying READ opens the channel for reading. 指定READ打开用于读取的通道。Specifying WRITE or APPEND opens the channel for writing. 指定WRITEAPPEND将打开写入通道。If none of these options are specified, then the channel is opened for reading.如果未指定这些选项,则打开通道进行读取。

The following code snippet reads a file and prints it to standard output:以下代码段读取文件并将其打印到标准输出:

public static void readFile(Path path) throws IOException {

    // Files.newByteChannel() defaults to StandardOpenOption.READ
    try (SeekableByteChannel sbc = Files.newByteChannel(path)) {
        final int BUFFER_CAPACITY = 10;
        ByteBuffer buf = ByteBuffer.allocate(BUFFER_CAPACITY);

        // Read the bytes with the proper encoding for this platform. If
        // you skip this step, you might see foreign or illegible
        // characters.
        String encoding = System.getProperty("file.encoding");
        while (sbc.read(buf) > 0) {
            buf.flip();
            System.out.print(Charset.forName(encoding).decode(buf));
            buf.clear();
        }
    }    
}

The following example, written for UNIX and other POSIX file systems, creates a log file with a specific set of file permissions. 下面的示例是为UNIX和其他POSIX文件系统编写的,它创建了一个具有特定文件权限集的日志文件。This code creates a log file or appends to the log file if it already exists. 此代码创建一个日志文件,如果日志文件已经存在,则将其附加到日志文件。The log file is created with read/write permissions for owner and read only permissions for group.日志文件是使用所有者的读/写权限和组的只读权限创建的。

import static java.nio.file.StandardOpenOption.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.util.*;

public class LogFilePermissionsTest {

  public static void main(String[] args) {
  
    // Create the set of options for appending to the file.
    Set<OpenOption> options = new HashSet<OpenOption>();
    options.add(APPEND);
    options.add(CREATE);

    // Create the custom permissions attribute.
    Set<PosixFilePermission> perms =
      PosixFilePermissions.fromString("rw-r-----");
    FileAttribute<Set<PosixFilePermission>> attr =
      PosixFilePermissions.asFileAttribute(perms);

    // Convert the string to a ByteBuffer.
    String s = "Hello World! ";
    byte data[] = s.getBytes();
    ByteBuffer bb = ByteBuffer.wrap(data);
    
    Path file = Paths.get("./permissions.log");

    try (SeekableByteChannel sbc =
      Files.newByteChannel(file, options, attr)) {
      sbc.write(bb);
    } catch (IOException x) {
      System.out.println("Exception thrown: " + x);
    }
  }
}

Methods for Creating Regular and Temporary Files创建常规文件和临时文件的方法

Creating Files创建文件

You can create an empty file with an initial set of attributes by using the createFile(Path, FileAttribute<?>) method. 可以使用createFile(Path, FileAttribute<?>)方法创建具有初始属性集的空文件。For example, if, at the time of creation, you want a file to have a particular set of file permissions, use the createFile method to do so. 例如,如果在创建文件时希望文件具有特定的文件权限集,请使用createFile方法。If you do not specify any attributes, the file is created with default attributes. 如果未指定任何属性,则将使用默认属性创建文件。If the file already exists, createFile throws an exception.如果文件已经存在,createFile将抛出异常。

In a single atomic operation, the createFile method checks for the existence of the file and creates that file with the specified attributes, which makes the process more secure against malicious code.在单个原子操作中,createFile方法检查文件是否存在,并使用指定的属性创建该文件,从而使进程更安全地抵御恶意代码。

The following code snippet creates a file with default attributes:以下代码段使用默认属性创建文件:

Path file = ...;
try {
    // Create the empty file with default permissions, etc.
    Files.createFile(file);
} catch (FileAlreadyExistsException x) {
    System.err.format("file named %s" +
        " already exists%n", file);
} catch (IOException x) {
    // Some other sort of failure, such as permissions.
    System.err.format("createFile error: %s%n", x);
}

POSIX File Permissions has an example that uses createFile(Path, FileAttribute<?>) to create a file with pre-set permissions.POSIX文件权限有一个使用createFile(Path, FileAttribute<?>)创建具有预设权限的文件的示例。

You can also create a new file by using the newOutputStream methods, as described in Creating and Writing a File using Stream I/O. 还可以使用newOutputStream方法创建新文件,如使用流I/O创建和写入文件中所述。If you open a new output stream and close it immediately, an empty file is created.如果打开新的输出流并立即关闭,则会创建一个空文件。

Creating Temporary Files创建临时文件

You can create a temporary file using one of the following createTempFile methods:可以使用以下createTempFile方法之一创建临时文件:

The first method allows the code to specify a directory for the temporary file and the second method creates a new file in the default temporary-file directory. 第一种方法允许代码为临时文件指定目录,第二种方法在默认临时文件目录中创建新文件。Both methods allow you to specify a suffix for the filename and the first method allows you to also specify a prefix. 这两种方法都允许您为文件名指定后缀,第一种方法还允许您指定前缀。The following code snippet gives an example of the second method:以下代码段给出了第二种方法的示例:

try {
    Path tempFile = Files.createTempFile(null, ".myapp");
    System.out.format("The temporary file" +
        " has been created: %s%n", tempFile)
;
} catch (IOException x) {
    System.err.format("IOException: %s%n", x);
}

The result of running this file would be something like the following:运行此文件的结果如下所示:

The temporary file has been created: /tmp/509668702974537184.myapp

The specific format of the temporary file name is platform specific.临时文件名的特定格式是特定于平台的。


Previous page: Managing Metadata (File and File Store Attributes)
Next page: Random Access Files