Java FileChannel.size()vs File.length()-在FileChannel.truncate()之后

时间:2019-04-07 15:17:43

标签: java filesize

我当时正在考虑将this question更改为我的情况。然后,我决定我的处境需要自己的问题,并希望能得到答案。调用FileChannel.truncate()以减小文件大小后,我调用FileChannel.size(),关闭FileChannel,然后调用File.length()。该文件存在于整个操作过程中。 FileChannel.size()总是准确的。在极少数情况下,File.length()将返回文件truncate()之前的大小。

下面是显示情况的代码。

public static void truncate(File file, long size) throws IOException
{
   FileChannel channel;
   Path path;
   long channelSize, fileLengthOpen, fileLengthClosed;

   path    = file.toPath();
   channel = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

   try
   {
      channel.truncate(size);

      channelSize    = channel.size();
      fileLengthOpen = file.length();
   }
   finally
   {
      channel.close();
   }

   fileLengthClosed = file.length();

   if ((channelSize != size) || (fileLengthOpen != size) || (fileLengthClosed != size))
      throw new IOException("The channel size or file length does not match the truncate size.  Channel: " + channelSize + " - Open File: " + fileLengthOpen + " - Closed File: " + fileLengthClosed + " - Truncate: " + size);
}

在极少数情况下,代码会引发IOExceptionchannelSize == sizefileLengthOpen == size,但fileLengthClosed!= size

为什么fileLengthClosed!= size?如何确保File.length()FileChannel.size()匹配?只要不强制刷新文件内容,刷新文件的元数据就可以了。刷新文件内容将导致不必要的文件I / O。

告诉我使用channelSizefileLengthOpen或忽略该问题的答案将不被接受。我还有另一个使用File.length()来确定文件长度的类文件。将channelSizefileLengthOpen传递给另一个类将需要将该值向上传递几个帧,然后向下传递几个帧。如果您建议我使用Files.size()来解决此问题,请说明原因。

我不确定这是否重要。我在Linux上运行Java 10。 (是的,我知道Java 10很旧,但是我坚持使用它,直到可以实现升级到Java 11的必要功能为止。)

编辑:过去,文件的多线程更新已引起问题。因此,我创建了一种文件锁定机制,以便在整个过程中只有一个线程可以独占地操作一个文件(或者多个线程可以读取该文件)。此外,传递给我的File的{​​{1}}对象是由调用线程创建的,并且仅由该线程使用。我可以保证进程中没有其他线程可以对磁盘上的文件或truncate()对象进行操作。

编辑:我将代码更改为在File之前和之后调用Files.size()channel.close()打开时,channel.size()File.length()Files.size()报告正确的大小。在channel之后,channel.close()File.length()很少是原始的较长文件长度,而不是截短的较短长度。

1 个答案:

答案 0 :(得分:0)

旋转以等待fileLengthClosed正确。这是代码。

while (true)
{
   fileLengthClosed = file.length();

   if (fileLengthClosed == size)
      break;

   Thread.sleep(1);
}

我已将此代码运行了3周,没有出现任何问题。一个问题是,如果文件长度被修改或file.length()从不更新,则没有超时代码。

此解决方案无法回答为什么File.length()首先是错误的。另外,调用Thread.sleep()表示我确实在等待其他操作完成,因此我应该强制该操作完成或阻止该操作。我不确定如何强制或阻止该操作。