Java 使用 Files.newByteChannel() 方法结合 SeekableByteChannel 接口可实现文件的高效读写操作,支持随机访问与通道式 I/O,通过指定 StandardOpenOption(如 READ、WRITE、CREATE)控制打开方式,常用于大文件处理;示例代码中使用 ByteBuffer 进行读写缓冲操作,提升性能和灵活性。本文主要介绍通过使用newByteChannel(Channel IO)读写文件(file),及使用的示例代码。

1、ByteChannel、SeekableByteChannel和newByteChannel

ByteChannel 接口提供了基本的读写功能,适用于字节流操作。它定义了两个主要方法:read()write(),分别用于从通道读取字节和将字节写入通道。ByteChannel 适用于普通的文件操作,但没有提供关于文件位置的操作。

SeekableByteChannel 接口

SeekableByteChannelByteChannel 的扩展,提供了额外的功能,允许保持通道中的当前位置,并能够更改该位置。通过该接口,可以:

  • 随机访问文件: 可以通过指定文件中的位置进行读取和写入操作,而不受文件内容顺序的限制。

  • 截断文件: 支持截断文件至指定大小。

  • 查询文件大小: 可以查询与通道关联的文件的当前大小。

这些功能使得对文件的随机访问成为可能,尤其在处理大文件时,能够高效地进行定位和访问操作。

newByteChannel 方法

newByteChannel 方法是 SeekableByteChannel 创建的关键方法之一,用于打开指定路径的文件并返回一个 SeekableByteChannel 实例。此方法提供了两种重载形式:

  1. newByteChannel(Path, OpenOption...):以指定的打开选项打开文件。

  2. newByteChannel(Path, Set<? extends OpenOption>, FileAttribute<?>...):以指定的打开选项和文件属性打开文件。

参数说明:

  • Path:文件路径。

  • OpenOption:指定文件打开的方式(如 READWRITEAPPEND 等)。

  • FileAttribute:指定文件的属性(例如创建时间等)。

访问更高级功能

通过 SeekableByteChannel 创建的通道可进一步转换为 FileChannel,从而提供更多的高级功能,例如:

  • 文件区域映射到内存:可以通过 FileChannel 将文件的某个区域直接映射到内存中,从而加快文件访问速度。

  • 文件区域锁定:使用 FileChannel 可以锁定文件的某个区域,防止其他进程在该区域进行访问或修改。

读取与写入通道 I/O

SeekableByteChannel 支持读写操作,因此它必须指定 READ 选项才能打开用于读取的通道,或者指定 WRITEAPPEND 选项打开用于写入的通道。若未指定,则默认打开通道进行读取。

import java.nio.channels.*;
import java.nio.file.*;
import java.nio.*;
import java.io.IOException;

public class ByteChannelExample {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("example.txt");

        // 打开文件并获得 SeekableByteChannel 实例
        SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ, StandardOpenOption.WRITE);
        
        // 读取数据
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        channel.read(buffer);
        buffer.flip();  // 准备读取数据
        while (buffer.hasRemaining()) {
            System.out.print((char) buffer.get());
        }

        // 写入数据
        buffer.clear();
        String data = "Hello, SeekableByteChannel!";
        buffer.put(data.getBytes());
        buffer.flip();
        channel.write(buffer);

        // 获取文件大小
        System.out.println("\nFile size: " + channel.size());

        // 关闭通道
        channel.close();
    }
}

2、使用newByteChannel读写文件

使用 newByteChannel 方法可以通过指定文件路径和打开选项(如 READWRITEAPPEND)创建一个 SeekableByteChannel 实例,该实例允许对文件进行随机读写操作。通过该通道,可以使用 read()write() 方法来读取和写入字节数据,并支持更改文件中的当前位置,实现文件的高效访问和修改。同时,还可以查询文件大小或截断文件。

//读取文件
try (SeekableByteChannel sbc = Files.newByteChannel(file)) {
    ByteBuffer buf = ByteBuffer.allocate(10);
//为这个平台读取正确编码的字节。如果
//你跳过这一步,你可能会看到像这样的东西
//当你希望看到拉丁风格的汉字时,就会想到汉字。
    String encoding = System.getProperty("file.encoding");
    while (sbc.read(buf) > 0) {
        buf.rewind();
        System.out.print(Charset.forName(encoding).decode(buf));
        buf.flip();
    }
} catch (IOException x) {
    System.out.println("caught exception: " + x);

以下示例是为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) {
    // 创建一组附加到文件的选项。
    Set<OpenOption> options = new HashSet<OpenOption>();
    options.add(APPEND);
    options.add(CREATE);
    // 创建自定义权限属性。
    Set<PosixFilePermission> perms =
      PosixFilePermissions.fromString("rw-r-----");
    FileAttribute<Set<PosixFilePermission>> attr =
      PosixFilePermissions.asFileAttribute(perms);
    // 将字符串转换为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);
    }
  }
}

相关文档https://docs.oracle.com/javase/tutorial/essential/io/file.html

推荐文档

相关文档

大家感兴趣的内容

随机列表