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

Java FileChannel.size()vs File.length()-在FileChannel.truncate()之后,java,filesize,Java,Filesize,我在考虑改变我的处境。然后我决定我的处境需要它自己的问题和希望的答案。调用FileChannel.truncate()以减小文件大小后,我调用FileChannel.size(),关闭FileChannel,然后调用file.length()。该文件在整个操作过程中都存在FileChannel.size()总是准确的。在极少数情况下,File.length()将返回truncate()之前的文件大小 下面是显示这种情况的代码 public static void truncate(File fi

我在考虑改变我的处境。然后我决定我的处境需要它自己的问题和希望的答案。调用
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);
}
在极少数情况下,代码抛出
IOException
<代码>频道大小=
大小
文件长度打开
=
大小
文件长度关闭
!=<代码>大小

为什么
文件长度已关闭
!=<代码>大小?如何确保
File.length()
匹配
FileChannel.size()
?只要不强制刷新文件内容,刷新文件元数据就可以了。刷新文件内容将导致不必要的文件I/O

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

我不确定这是否重要。我正在Linux上运行Java10。(是的,我知道Java 10很旧,但我一直坚持使用它,直到我能够实现升级到Java 11所需的功能。)

编辑:过去,文件的多线程更新会导致问题。出于这个原因,我创建了一个文件锁定机制,这样整个进程中只有一个线程可以独占地操作一个文件(或者多个线程可以读取该文件)。此外,传递给my
truncate()
文件
对象是由调用线程创建的,并且仅由该线程使用。我可以保证进程中没有其他线程可以对磁盘上的文件或
文件
对象进行操作


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

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

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

   if (fileLengthClosed == size)
      break;

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


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

为什么不使用
Files.size()
文件
类应该已经被允许和平死亡。您是否尝试过查看
文件.size()
是否存在此问题?众所周知,Windows在文件打开时不会更新文件元数据。我的代码库中大约有90个位置使用了
文件.length()
。如果我能证明它解决了问题,我会将代码更改为
Files.size()
。我更改了
truncate()
以检查
文件.size()
在关闭
FileChannel
之前和之后的情况,我将看看会发生什么。。。重现此问题可能需要几天时间。不幸的是,此问题不会在Windows上重现。但是,这并不能说明什么,因为这个问题在Linux上并不经常出现。@realponsign我在使用
Files.size()
后更新了这个问题
Files.size()
File.length()
具有相同的问题。