Java NIO FileChannel

Java NIO 文件管道,原文地址:http://tutorials.jenkov.com/java-nio/file-channel.html

Java NIO 文件管道连接着文件。使用文件管道你可以操作文件,从中读写数据。Java NIO 文件管道相对于标准 Java IO 是一种可选的读写文件的方式。
文件管道不能被设置为非阻塞模式,它永远运行于阻塞模式。

Opening a FileChannel

你在使用一个文件管道之前必须先得打开它,但是你又不能直接打开一个文件管道,你必须通过 InputStream, OutputStream 或者 RandomAccessFile 来获取一个文件管道。下面展示了使用一个 RandomAccessFile 打开一个文件管道的代码:

1
2
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();

从一个文件管道中读取数据

你可以调用 read() 方法从文件管道中读取数据,下面是一个小例子:

1
2
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);

首先需要先分配一个字节缓冲区,然后将文件管道中的数据读入字节缓冲区中。inChannel.read() 方法返回值表示有多少数据写入了缓冲区内。如果返回了 -1,则代表已经读取到了文件末尾。

向一个文件管道中写入数据

使用 FileChannel.write() 方法写数据到文件管道,该方法使用一个缓冲区对象作为参数。下面是一个小例子:

1
2
3
4
5
6
7
8
9
10
11
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}

请注意,FileChannel.write() 方法是在一个 while 循环中被调用的。因为我们不知道缓冲区中有多少数据可以写入管道中,所以我们一直循环调用该方法直到缓冲区中无数据可写了。

关闭一个文件管道

当你用完了一个文件管道之后,你必须关闭它。下面是关闭的代码:
channel.close();

文件管道的位置

当你从一个文件管道中读写数据时,必须要指定一个确定的位置才行。你可以通过调用 position() 方法来获取文件管道当前的位置。你也可以调用 position(long pos) 方法来设置文件管道的位置。下面是这个方法使用的例子:

1
2
long pos = channel.position();
channel.position(pos + 123);

如果你把位置设置在文件大小范围之外,并尝试从中读取数据的话,你将会得到代表着文件末尾的 -1 返回值。
如果你把位置设置在文件大小范围之外,并尝试写入数据的话,文件大小会自动扩展以适应你设置的位置和写入的数据。这可能会产生“文件窟窿”,在写入数据的物理磁盘上也会有相应的隔代。

文件管道大小

文件管道的 size() 方法会返回当前管道所连接文件的文件大小。下面是使用小例子:
long fileSize = channel.size();

文件管道的截取

你可以通过调用 FileChannel.truncate() 方法来截取一个文件。当你截取一个文件时,你需要指定一个截取的长度。下面是使用小例子:
channel.truncate(1024);
这个例子中将文件截取为 1024 字节的长度。

FileChannel Force

方法 FileChannel.force() 的作用是将管道中未写入文件的数据全部写入到磁盘文件。为了性能操作系统可能会在内存中缓存我们写入到磁盘文件的数据,除非你调用了 force() 方法。
force() 方法会要求一个布尔值作为参数,这个布尔值决定是否将元数据(例如权限等)写入文件。下面是将数据和元数据写入文件的一个例子:
channel.force(true);