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