系列中的上一篇
当前教程
读取和写入二进制文件
系列中的下一篇

系列中的上一篇: 读取和写入文本文件

系列中的下一篇: 装饰 IO 流

读取和写入二进制文件

 

使用流 I/O 读取文件

要打开一个文件进行读取,可以使用 newInputStream(Path, OpenOption...) 方法。此方法返回一个未缓冲的输入流,用于从文件中读取字节。

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);
}

 

使用流 I/O 创建和写入文件

可以使用 newOutputStream(Path, OpenOption...) 方法创建文件、追加到文件或写入文件。此方法打开或创建用于写入字节的文件,并返回一个未缓冲的输出流。

该方法接受一个可选的 OpenOption 参数。如果未指定任何打开选项,并且文件不存在,则创建一个新文件。如果文件存在,则将其截断。此选项等效于使用 CREATETRUNCATE_EXISTING 选项调用该方法。

以下示例打开一个日志文件。如果文件不存在,则创建它。如果文件存在,则打开它以进行追加。

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);
    }
  }
}

 

使用通道 I/O 读取和写入文件

虽然流 I/O 每次读取一个字符,但通道 I/O 每次读取一个缓冲区。 ByteChannel 接口提供基本的读写功能。 SeekableByteChannel 是一个 ByteChannel,它具有在通道中维护位置并更改该位置的能力。 SeekableByteChannel 还支持截断与通道关联的文件以及查询文件的大小。

能够移动到文件中的不同点,然后从该位置读取或写入,使得随机访问文件成为可能。有关更多信息,请参见随机访问文件部分。

有两种方法可以读取和写入通道 I/O。

注意: newByteChannel() 方法返回一个 SeekableByteChannel 的实例。使用默认文件系统,您可以将此可搜索字节通道转换为 FileChannel,从而提供对更多高级功能的访问,例如将文件的一部分直接映射到内存中以实现更快的访问,锁定文件的一部分以防止其他进程访问它,或者从绝对位置读取和写入字节,而不会影响通道的当前位置。

两种 newByteChannel() 方法都允许您指定一个 OpenOption 选项列表。除了一个选项外, newOutputStream() 方法使用的相同打开选项都受支持: READ 是必需的,因为 SeekableByteChannel 支持读写。

指定 READ 将打开通道以进行读取。指定 WRITEAPPEND 将打开通道以进行写入。如果未指定这些选项中的任何一个,则通道将打开以进行读取。

以下代码片段读取文件并将其打印到标准输出

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();
        }
    }
}

以下示例(为 UNIX 和其他 POSIX 文件系统编写)创建一个具有特定文件权限的日志文件。此代码创建一个日志文件,如果它已经存在,则追加到该日志文件。日志文件以所有者可读写、组只读的权限创建。

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);
    }
  }
}

上次更新: 2023 年 1 月 25 日


系列中的上一篇
当前教程
读取和写入二进制文件
系列中的下一篇

系列中的上一篇: 读取和写入文本文件

系列中的下一篇: 装饰 IO 流