Java RandomAccessFile.seek()是如何工作的?

Java RandomAccessFile.seek()是如何工作的?,java,file,randomaccessfile,bufferedoutputstream,Java,File,Randomaccessfile,Bufferedoutputstream,根据调查,事实如下: seek(longbyteposition)方法简单地说,将指针移动到 用bytePosition参数指定的位置 当bytePosition大于文件长度时,文件 除非在(新)端写入字节,否则长度不会更改 如果在跳过的长度中存在数据,则会保留此类数据 原封不动 然而,我想知道的情况是:当有一个没有数据(0字节)的文件时,我执行以下代码: file.seek(100000-1); file.write(0); 所有100000字节几乎立即被0填满。我可以在10毫秒内时钟超

根据调查,事实如下:

  • seek(longbyteposition)
    方法简单地说,将指针移动到 用
    bytePosition
    参数指定的位置
  • bytePosition
    大于文件长度时,文件 除非在(新)端写入字节,否则长度不会更改
  • 如果在跳过的长度中存在数据,则会保留此类数据 原封不动
然而,我想知道的情况是:当有一个没有数据(0字节)的文件时,我执行以下代码:

file.seek(100000-1);
file.write(0);
所有100000字节几乎立即被
0
填满。我可以在10毫秒内时钟超过200GB

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

时间差异的原因是什么?有没有更有效的方法来创建一个
n
字节的文件并用
0
s填充它

编辑: 如果数据不是实际写入的,文件中如何填充数据? 示例代码:

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


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

您的操作系统和文件系统支持稀疏文件,在这种情况下,将实现seek以利用此功能

这实际上与Java无关,它只是C库中
fseek
fwrite
函数的一个特性,它们很可能是您正在使用的JRE上的后台文件实现

更多信息:

有没有更有效的方法来创建一个n字节的文件并用0填充它


在支持它的操作系统上,您可以将文件复制到所需大小,而无需发出
write
调用。但是,这在Java API中似乎不可用。

当您将100000字节写入一个
BufferedOutputStream
时,您的程序显式地访问文件的每个字节并写入一个零

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

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

例如,当您读取稀疏文件时,通过
fseek()
ing到字节50000,然后读取,操作系统可以说“好的,我没有为字节50000分配磁盘空间,因为我注意到字节0到100000是空的。因此我可以为该字节返回
0
”。这对调用方是不可见的

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


更一般地说,
fseek()
直接指向文件中的某个位置,因此它是O(1)而不是O(n)。如果将一个文件与一个数组进行比较,这就像执行
x=arr[n]
而不是
for(i=0;我猜文件大小是“注意到的”,但实际的块没有写入磁盘。刷新/关闭需要多长时间?(参见此处)我的猜测是一样的,但我确实打开了文件并检查了它。当我没有写入最后一个字节时,它是空的,生成的文件大小为0字节。当我写入最后一个字节时,直到最后一个字节的每个字节都被0填充,文件大小作为输入。整个过程,使用close()包含的操作是问题中指定的时间(这就是为什么我感到惊讶!)当你阅读该方法的源代码时,你不明白什么?在要求其他人阅读源代码之前,你是否阅读了源代码?你是否为自己工作?@JarrodRoberson这是一种本机方法。操作系统如何处理这一问题非常依赖于哪个操作系统@RangaRajan。至于数据是如何编写的,下面的答案对此进行了解释w、 如果文件是稀疏的,则所有0的处理方式都不同。请您详细说明一下,好吗?另外seek()是如何处理的实现的方法?有什么方法可以让我看到内置库方法是如何实现的吗?@RangaRajan这适合作为另一个问题发布。谢谢answers@Gray稀疏文件是否也会覆盖已删除的数据?(已删除但尚未覆盖的数据)稀疏文件必须是稀疏的。它必须通过seek-ing创建。如果您将0或任何其他字节写入该文件,则该文件不是稀疏的。在文件周围搜索并不会删除任何内容。它只是将文件指针移动到@RangaRajan附近。这个答案也会处理您的编辑@RangaRajan。数据是0s,由稀疏文件处理。谢谢ranswers@slim稀疏文件也会覆盖已删除的数据吗?(数据已删除但尚未覆盖)阅读此说明后,我可以理解它不会覆盖,但我进行了实验,发现我无法使用梨形的Recuva恢复文件。(Windows 10)如果您还有其他问题,请作为新问题提问-但您必须解释“覆盖已删除的数据”和“已删除但尚未覆盖的数据”的含义。此外,它可能属于不同的Stack Exchange站点,具体取决于您询问的操作系统。