1、ByteChannel、SeekableByteChannel和newByteChannel
ByteChannel
接口提供了基本的读写功能,适用于字节流操作。它定义了两个主要方法:read()
和 write()
,分别用于从通道读取字节和将字节写入通道。ByteChannel
适用于普通的文件操作,但没有提供关于文件位置的操作。
SeekableByteChannel 接口
SeekableByteChannel
是 ByteChannel
的扩展,提供了额外的功能,允许保持通道中的当前位置,并能够更改该位置。通过该接口,可以:
随机访问文件: 可以通过指定文件中的位置进行读取和写入操作,而不受文件内容顺序的限制。
截断文件: 支持截断文件至指定大小。
查询文件大小: 可以查询与通道关联的文件的当前大小。
这些功能使得对文件的随机访问成为可能,尤其在处理大文件时,能够高效地进行定位和访问操作。
newByteChannel
方法
newByteChannel
方法是 SeekableByteChannel
创建的关键方法之一,用于打开指定路径的文件并返回一个 SeekableByteChannel
实例。此方法提供了两种重载形式:
newByteChannel(Path, OpenOption...)
:以指定的打开选项打开文件。newByteChannel(Path, Set<? extends OpenOption>, FileAttribute<?>...)
:以指定的打开选项和文件属性打开文件。
参数说明:
Path
:文件路径。OpenOption
:指定文件打开的方式(如READ
、WRITE
、APPEND
等)。FileAttribute
:指定文件的属性(例如创建时间等)。
访问更高级功能
通过 SeekableByteChannel
创建的通道可进一步转换为 FileChannel
,从而提供更多的高级功能,例如:
文件区域映射到内存:可以通过
FileChannel
将文件的某个区域直接映射到内存中,从而加快文件访问速度。文件区域锁定:使用
FileChannel
可以锁定文件的某个区域,防止其他进程在该区域进行访问或修改。
读取与写入通道 I/O
SeekableByteChannel
支持读写操作,因此它必须指定 READ
选项才能打开用于读取的通道,或者指定 WRITE
或 APPEND
选项打开用于写入的通道。若未指定,则默认打开通道进行读取。
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
方法可以通过指定文件路径和打开选项(如 READ
、WRITE
、APPEND
)创建一个 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