Java FileChannel.size() 与 File.length() - 在 FileChannel.truncate() 之后
Java FileChannel.size() vs File.length() - After FileChannel.truncate()
我正在考虑将 this question 改成我的情况。然后我决定我的情况需要自己的问题并希望得到答案。在调用 FileChannel.truncate()
减小文件大小后,我调用 FileChannel.size()
,关闭 FileChannel
,然后调用 File.length()
。文件存在于整个操作过程中。 FileChannel.size()
总是准确的。在极少数情况下,File.length()
将 return 为 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
。 channelSize
== size
和 fileLengthOpen
== size
但 fileLengthClosed
!= size
.
为什么 fileLengthClosed
!= size
?如何确保 File.length()
匹配 FileChannel.size()
?只要不强制刷新文件的内容,刷新文件的元数据就可以了。刷新文件的内容会产生不需要的文件 I/Os.
告诉我使用 channelSize
或 fileLengthOpen
或忽略问题的答案将不会被接受。我有另一个 class 文件,它使用 File.length()
来确定文件的长度。将 channelSize
或 fileLengthOpen
传递给另一个 class 需要将值向上传递几帧,然后返回几帧。如果您建议我使用 Files.size()
来解决问题,请说明原因。
我不确定这是否重要。我是 运行 Java 10 Linux。 (是的,我知道 Java 10 已经过时了,但我一直坚持使用它,直到我可以实现必要的功能来升级到 Java 11。)
编辑:过去,文件的多线程更新引起了问题。为此,我创建了一种文件锁定机制,使得整个进程中只有1个线程可以独占对一个文件进行操作(或者多个线程可以读取该文件)。此外,传递给我的 truncate()
的 File
对象是由调用线程创建的,并且仅由该线程使用。我可以保证进程中没有其他线程可以对磁盘上的文件或File
对象进行操作。
编辑:我将代码更改为在 channel.close()
之前和之后调用 Files.size()
。 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()
表明我真的在等待其他操作完成,我真的应该强制该操作完成或阻止该操作。我不确定如何强制或阻止该操作。
我正在考虑将 this question 改成我的情况。然后我决定我的情况需要自己的问题并希望得到答案。在调用 FileChannel.truncate()
减小文件大小后,我调用 FileChannel.size()
,关闭 FileChannel
,然后调用 File.length()
。文件存在于整个操作过程中。 FileChannel.size()
总是准确的。在极少数情况下,File.length()
将 return 为 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
。 channelSize
== size
和 fileLengthOpen
== size
但 fileLengthClosed
!= size
.
为什么 fileLengthClosed
!= size
?如何确保 File.length()
匹配 FileChannel.size()
?只要不强制刷新文件的内容,刷新文件的元数据就可以了。刷新文件的内容会产生不需要的文件 I/Os.
告诉我使用 channelSize
或 fileLengthOpen
或忽略问题的答案将不会被接受。我有另一个 class 文件,它使用 File.length()
来确定文件的长度。将 channelSize
或 fileLengthOpen
传递给另一个 class 需要将值向上传递几帧,然后返回几帧。如果您建议我使用 Files.size()
来解决问题,请说明原因。
我不确定这是否重要。我是 运行 Java 10 Linux。 (是的,我知道 Java 10 已经过时了,但我一直坚持使用它,直到我可以实现必要的功能来升级到 Java 11。)
编辑:过去,文件的多线程更新引起了问题。为此,我创建了一种文件锁定机制,使得整个进程中只有1个线程可以独占对一个文件进行操作(或者多个线程可以读取该文件)。此外,传递给我的 truncate()
的 File
对象是由调用线程创建的,并且仅由该线程使用。我可以保证进程中没有其他线程可以对磁盘上的文件或File
对象进行操作。
编辑:我将代码更改为在 channel.close()
之前和之后调用 Files.size()
。 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()
表明我真的在等待其他操作完成,我真的应该强制该操作完成或阻止该操作。我不确定如何强制或阻止该操作。