Я думал об изменении этого вопроса в моей ситуации.Затем я решил, что моей ситуации нужен собственный вопрос и, надеюсь, ответы.После вызова 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
.channelSize
== size
и fileLengthOpen
== size
но fileLengthClosed
! = size
.
Почему fileLengthClosed
! = size
?Как мне обеспечить File.length()
совпадений FileChannel.size()
?Очистка метаданных файла будет в порядке, если только она не приводит к принудительной очистке содержимого файла.При очистке содержимого файла могут возникнуть ненужные операции ввода-вывода.
Ответы, указывающие на использование channelSize
или fileLengthOpen
или игнорирование проблемы, не будут приняты.У меня есть другой файл класса, который использует File.length()
, чтобы определить длину файла.Передача channelSize
или fileLengthOpen
другому классу потребует передачи значения вверх по стеку на несколько кадров, а затем обратно на несколько кадров вниз.Если вы предлагаете мне использовать Files.size()
для решения проблемы, объясните, почему.
Я не уверен, имеет ли это значение.Я использую Java 10 в Linux.(Да, я знаю, что Java 10 старая, но я застрял с ней, пока не смогу реализовать необходимые функции для обновления до Java 11.)
Редактировать: В прошлом многопоточные обновления файлов вызывалипроблемы.По этой причине я создал механизм блокировки файлов, чтобы только один поток во всем процессе мог работать исключительно с файлом (или несколько потоков могут читать файл).Кроме того, объект File
, переданный моему truncate()
, был создан вызывающим потоком и используется только этим потоком.Я могу гарантировать, что никакой другой поток в этом процессе не сможет работать с файлом на диске или объектом File
.
Редактировать: Я изменил код для вызова Files.size()
до и после channel.close()
.channel.size()
, File.length()
и Files.size()
сообщают правильный размер при открытом channel
.Сразу после channel.close()
, File.length()
и Files.size()
в редких случаях исходная более длинная длина файла, а не усеченная более короткая длина.