原始问题是:
我想问一下,先用FileChannel position,再读。和用int read(ByteBuffer dst, long position)这个方法。效果是不是一样的?
例如在下面的这些代码。
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
public class IOLearning {
public static void main(String[] args) throws IOException {
Path path = Paths.get("hello.txt");
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ);
//先使用position,再read
ByteBuffer byteBuffer = ByteBuffer.allocate(1);
fileChannel.position(2);
fileChannel.read(byteBuffer);
System.out.println(Arrays.toString(byteBuffer.array()));
//再读一次
ByteBuffer byteBuffer1 = ByteBuffer.allocate(1);
fileChannel.read(byteBuffer1);
System.out.println(Arrays.toString(byteBuffer1.array()));
//使用read(buffer, position)方法
ByteBuffer byteBuffer2 = ByteBuffer.allocate(1);
fileChannel.read(byteBuffer2, 2);
System.out.println(Arrays.toString(byteBuffer2.array()));
//再读一次
ByteBuffer byteBuffer3 = ByteBuffer.allocate(1);
fileChannel.read(byteBuffer3);
System.out.println(Arrays.toString(byteBuffer3.array()));
//再用一次position
ByteBuffer byteBuffer4 = ByteBuffer.allocate(1);
fileChannel.position(1);
fileChannel.read(byteBuffer);
System.out.println(Arrays.toString(byteBuffer4.array()));
//再读一次
ByteBuffer byteBuffer5 = ByteBuffer.allocate(1);
fileChannel.read(byteBuffer5);
System.out.println(Arrays.toString(byteBuffer5.array()));
}
}
其中hello.txt的内容为:
123456789
输出的内容为:
[51]
[52]
[51]
[53]
[0]
[50]
我们可以发现position方法会改变位置,read()不会。先用FileChannel position,再读,和用int read(ByteBuffer dst, long position)这个方法,效果是不一样的。不知道position方法对性能影响大不大。
这个问题是来自我去修改一个时序数据库的底层文件格式遇到的。你可以再这里找到这个文件(https://github.com/apache/incubator-iotdb/blob/master/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java)。这里值得注意的是tsFileInput指向的对象实际上使用了FileChannel,不论是调用了position还是read,就是在调用FileChannel的position和read。
/**
* this function does not modify the position of the file reader.
*
* @param movePosition whether move the position of the file reader after reading the magic header
* to the end of the magic head string.
*/
public String readHeadMagic(boolean movePosition) throws IOException {
ByteBuffer magicStringBytes = ByteBuffer.allocate(TSFileConfig.MAGIC_STRING.length());
if (movePosition) {
tsFileInput.position(0);
tsFileInput.read(magicStringBytes);
} else {
tsFileInput.read(magicStringBytes, 0);
}
magicStringBytes.flip();
return new String(magicStringBytes.array());
}