0%

FileChannel读写文件与filp()等方法

使用FileChannel读写文件,我们只需要关注缓冲区Buffer,只需要对Buffer进行读写操作。

我们关注的只是Buffer的读写,

当需要向文件中写入数据时,将数据写入Buffer,然后使用Channel读取Buffer中的内容写出到文件。对于Buffer,这是一个“写入——读取”的过程。

当需要从文件中读取数据时,使用channel读取文件的内容写入到Buffer,然后读取Buffer的数据。对于Buffer,这是一个“写入——读取”的过程。

Buffer有三个重要的参数:position,capaticy,limit。position可以是记录当前位置的指针,读写将从position位置开始;capaticy是Buffer的最大容量;limit可以看作是当前Buffer的“实际长度”,在向Buffer写入数据时,limit应当与capaticy相同;在从Buffer读取数据时,limit应当指向当前存储的内容的末尾,也即是position指向的位置。

使用channel读写文件通常如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Path path = Paths.get("FileChannelTest");
if (!Files.exists(path)) {
Files.createFile(path);
}

FileChannel channelWrite = FileChannel.open(path, StandardOpenOption.WRITE);

ByteBuffer byteBuffer1 = ByteBuffer.allocate(1024);

byteBuffer1.clear();
byteBuffer1.putChar('a');
byteBuffer1.putInt(123);

byteBuffer1.flip();
channelWrite.write(byteBuffer1);

channelWrite.close();

FileChannel channelRead = FileChannel.open(path, StandardOpenOption.READ);

ByteBuffer byteBuffer2 = ByteBuffer.allocate(1024);

byteBuffer2.clear();
channelRead.read(byteBuffer2);

byteBuffer2.flip();
System.out.println(byteBuffer2.getChar());
System.out.println(byteBuffer2.getInt());

channelRead.close();

需要特别的注意的是clear()和flip()方法。注释说起来绕口,直接对着代码看,

1
2
3
4
5
6
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}

clear()方法将指针pisition放回起点,limit指向缓冲区末尾边界,那么调用clear()之后,如果向Buffer写入数据,则从起点开始写,最大可以写入到末尾边界,覆盖原有内容。

1
2
3
4
5
6
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}

flip()方法将limit设置为当前指针位置,指针返回缓冲区首部,那么调用flip()之后,如果从Buffer读取数据,将读到0~limit之间的内容,也就是上次写入到Buffer中的内容。

所以在向Buffer写入数据时,如果要覆盖,应该先调用clear();从Buffer读取内容时,应当先调用flip()。