JAVA在使用seek之后,使用RandomAccessFile变得非常缓慢。原因是什么?

3
这是我的测试代码。
long fileSize = 1024 * 1024 * 512L;
byte[] bts = new byte[8];

RandomAccessFile randomAccessFile = new RandomAccessFile("f:/test.data", "rw");
randomAccessFile.setLength(fileSize);

randomAccessFile.seek(0);
long time = System.nanoTime();
randomAccessFile.write(bts);
System.out.println("write1 use:" + (System.nanoTime() - time));

randomAccessFile.seek(1024 * 1024 * 256L);
time = System.nanoTime();
randomAccessFile.write(bts);
System.out.println("write2 use:" + (System.nanoTime() - time));

打印

write1 use:181051
write2 use:2029338072

可以看出,写入操作被重复了9次,而第二次比第一次慢了10000倍。

因此,我想问为什么查找会导致文件写入如此缓慢。有没有解决方法?


2
这将创建大约256MB的数据,因为由于巨大的偏移量,第二次查找时需要这么多数据。你为什么要寻找这么远? - tadman
我正在开发一个高速HTTP下载器,需要同时下载多个块,因此我希望在块下载响应到达时对文件进行查找。 - liwei2633
测试较小的偏移量,以查看延迟是否成比例。或者,先将数据写入分块文件,然后再进行组装。 - tadman
3
你的操作系统和文件系统类型是什么?要使类似这样的操作正常运行且不会非常缓慢,操作系统和文件系统必须支持稀疏文件。否则,当你写入一个大的偏移量且之前没有任何数据时,系统需要像@tadman在评论中所述那样创建所有的数据。同时注意,你可以使用FileChannel.write(ByteBuffer src, long position)方法在无需寻址的情况下向文件的任意位置写入数据。 - Andrew Henle
2
非常感谢。我尝试使用Files.newByteChannel()和StandardOpenOption.SPARSE选项。它非常快速。 - liwei2633
显示剩余2条评论
1个回答

1
你想要创建一个稀疏文件。https://zh.wikipedia.org/wiki/%E7%A9%BA%E6%B0%B4%E6%96%87%E4%BB%B6
final ByteBuffer buf = ByteBuffer.allocate(4).putInt(2);
buf.rewind();

final OpenOption[] options = {
    StandardOpenOption.WRITE,
    StandardOpenOption.CREATE_NEW,
    StandardOpenOption.SPARSE
};
final Path path = Paths.get("/tmp/foo");
Files.deleteIfExists(path);

try (
    final SeekableByteChannel channel
        = Files.newByteChannel(path, options);
) {
    channel.position(1L << 31);
    channel.write(buf);
}

这段代码来自什么是StandardOpenOption.SPARSE的用途?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接