gpt4 book ai didi

java - RandomAccessFile.seek() 如何工作?

转载 作者:行者123 更新时间:2023-12-02 10:58:28 25 4
gpt4 key购买 nike

根据 API ,这些是事实:

  • seek(long bytePosition)方法简单来说就是将指针移动到用 bytePosition 指定的位置参数。
  • bytePosition大于文件长度,则文件除非在(新)末尾写入一个字节,否则长度不会改变。
  • 如果数据存在于跳过的长度中,则保留该数据未受影响。

但是,我很好奇的情况是:当存在一个没有数据(0字节)的文件时,我执行以下代码:

file.seek(100000-1);
file.write(0);

这 100,000 字节全部填充为 0几乎是瞬间。我可以在 10 毫秒内读取超过 200GB 的数据。

但是当我尝试使用其他方法写入 100000 字节时,例如 BufferedOutputStream同样的过程需要几乎无限长的时间。

造成这种时间差异的原因是什么?有没有更有效的方法来创建n的文件字节并用 0 填充它是吗?

编辑:如果数据没有真正写入,那么文件是如何填充数据的呢?示例代码:

RandomAccessFile out=new RandomAccessFile("D:/out","rw");
out.seek(100000-1);
out.write(0);
out.close();

这是输出:

Output

另外,如果文件足够大,由于空间不足,我无法再写入磁盘。

最佳答案

当您将 100,000 字节写入 BufferedOutputStream 时,您的程序显式访问文件的每个字节并写入零。

当您使用RandomAccessFile.seek()时在本地文件上,您间接使用 C 系统调用 fseek() 。如何处理取决于操作系统。

在大多数现代操作系统中,sparse files都支持。这意味着,如果您请求一个空的 100,000 字节文件,则实际上不会使用 100,000 字节的磁盘空间。当您写入字节 100,001 时,操作系统仍然不使用 100,001 字节的磁盘。它为包含“真实”数据的 block 分配少量空间,并单独跟踪空闲空间。

当您读取一个稀疏文件时,例如 fseek()到字节 50,000,然后读取,操作系统可以说“好吧,我没有为字节 50,000 分配磁盘空间,因为我注意到字节 0 到 100,000 是空的。因此我可以为此字节返回 0。”。这对于调用者来说是不可见的。

这具有节省磁盘空间和提高速度的双重目的。您已经注意到速度的提高。

更一般地说,fseek()直接转到文件中的某个位置,因此时间复杂度为 O(1) 而不是 O(n)。如果将文件与数组进行比较,就像 x = arr[n]而不是for(i = 0; i<=n; i++) { x = arr[i]; }

这个描述以及维基百科上的描述可能足以理解为什么先求字节 100,000 然后写入比写入 100,000 个零更快。不过你可以阅读Linux内核源代码来看看稀疏文件是如何实现的,你可以阅读RandomAccessFile JDK 中的源代码和 JRE 源代码,看看它们如何交互。但是,这可能比您需要的更详细。

关于java - RandomAccessFile.seek() 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42421768/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com