При поиске, я вижу, что использование java.io.File#length()
может быть медленным.
FileChannel
есть size()
метод, который также доступен.
Есть ли эффективный способ в Java, чтобы получить размер файла?
При поиске, я вижу, что использование java.io.File#length()
может быть медленным.
FileChannel
есть size()
метод, который также доступен.
Есть ли эффективный способ в Java, чтобы получить размер файла?
Ответы:
Ну, я попытался измерить это с помощью кода ниже:
Для запусков = 1 и итераций = 1 метод URL быстрее всего следует за каналом. Я запускаю это с некоторой свежей паузой около 10 раз. Таким образом, для однократного доступа использование URL-адреса является самым быстрым способом, о котором я могу думать:
Для прогонов = 5 и итераций = 50 картина рисуется иначе.
Файл должен кэшировать вызовы файловой системы, в то время как каналы и URL имеют некоторые накладные расходы.
Код:
источник
stream.available()
не возвращает длину файла. Возвращает количество байтов, доступных для чтения, без блокировки других потоков. Это не обязательно то же количество байтов, что и длина файла. Чтобы получить реальную длину из потока, вам действительно нужно прочитать ее (и посчитать считанные байты).Тест, данный GHad, измеряет множество других вещей (таких как отражение, создание объектов и т. Д.) Помимо определения длины. Если мы попытаемся избавиться от этих вещей, то за один звонок я получу следующее время в микросекундах:
За 100 прогонов и 10000 итераций я получаю:
Я выполнил следующий модифицированный код, указав в качестве аргумента имя файла размером 100 МБ.
источник
Все контрольные примеры в этом посте имеют недостатки, так как имеют доступ к одному и тому же файлу для каждого протестированного метода. Таким образом, кеширование диска дает преимущества при тестах 2 и 3. Чтобы доказать свою точку зрения, я взял контрольный пример, предоставленный GHAD, и изменил порядок перечисления. Ниже приведены результаты.
Глядя на результат, я думаю, File.length () действительно победитель.
Порядок проверки - это порядок вывода. Вы даже можете видеть, что время, затрачиваемое на моем компьютере, варьируется между выполнениями, но File.Length (), когда не первый, и получение первого доступа к диску выиграно.
источник
Когда я изменяю ваш код, чтобы использовать файл, доступ к которому осуществляется по абсолютному пути, а не по ресурсу, я получаю другой результат (для 1 запуска, 1 итерации и файла размером 100 000 байт - время для 10-байтового файла совпадает с 100 000 байтов )
ДЛИНА сумма: 33, за итерацию: 33,0
Сумма КАНАЛА: 3626, за Итерацию: 3626.0
Сумма URL: 294, за итерацию: 294,0
источник
В ответ на тест rgrig, время, необходимое для открытия / закрытия экземпляров FileChannel & RandomAccessFile, также необходимо учитывать, так как эти классы откроют поток для чтения файла.
После изменения эталонного теста я получил эти результаты за 1 итерацию для файла размером 85 МБ:
Для 10000 итераций в одном файле:
Если все, что вам нужно, это размер файла, то file.length () - самый быстрый способ сделать это. Если вы планируете использовать файл для других целей, таких как чтение / запись, тогда лучше использовать RAF. Только не забудьте закрыть файл подключения :-)
источник
Я столкнулся с этой же проблемой. Мне нужно было получить размер файла и дату изменения в 90000 файлов на сетевом ресурсе. Используя Java и будучи максимально минималистичным, это займет очень много времени. (Мне нужно было получить URL из файла, а также путь к объекту. Так что он несколько варьировался, но больше часа.) Затем я использовал собственный исполняемый файл Win32 и выполнил ту же задачу, просто выгрузив файл путь, измененный и размер к консоли и выполненный из Java. Скорость была потрясающая. Собственный процесс и обработка строк для чтения данных могут обрабатывать более 1000 элементов в секунду.
Поэтому, несмотря на то, что люди оценили приведенный выше комментарий, это правильное решение, и оно действительно решило мою проблему. В моем случае я знал, какие папки мне нужны заранее, и мог передать это в командной строке своему приложению win32. Я шел от часов, чтобы обработать каталог до минут.
Проблема также, кажется, была специфичной для Windows. OS X не имела такой же проблемы и могла получить доступ к информации о сетевых файлах так же быстро, как и ОС.
Обработка файлов Java в Windows ужасна. Локальный доступ к файлам для файлов все же хорошо. Это были просто сетевые ресурсы, которые вызвали ужасную производительность. Windows может получить информацию об общем сетевом ресурсе и вычислить общий размер за минуту.
--Бен
источник
Если вы хотите размер файла нескольких файлов в каталоге, используйте
Files.walkFileTree
. Вы можете получить размер из того,BasicFileAttributes
что вы получите.Это намного быстрее, чем вызов
.length()
результатаFile.listFiles()
или использованиеFiles.size()
результатаFiles.newDirectoryStream()
. В моих тестовых случаях это было примерно в 100 раз быстрее.источник
Files.walkFileTree
доступно на Android 26+.На самом деле, я думаю, что «лс» может быть быстрее. В Java определенно есть некоторые проблемы, связанные с получением информации о файле. К сожалению, нет эквивалентного безопасного метода рекурсивного ls для Windows. (DIR / S cmd.exe может запутаться и генерировать ошибки в бесконечных циклах)
В XP при доступе к серверу в локальной сети у меня уходит 5 секунд в Windows, чтобы получить количество файлов в папке (33 000) и общий размер.
Когда я повторяю это в Java, это занимает у меня более 5 минут. Я начал измерять время, необходимое для выполнения функций file.length (), file.lastModified () и file.toURI (), и обнаружил, что 99% времени уходит на эти 3 вызова. 3 звонка, которые мне действительно нужно сделать ...
Разница для 1000 файлов составляет 15 мс по сравнению с 1800 мс на сервере. Сканирование пути сервера в Java смехотворно медленно. Если нативная ОС может быстро сканировать ту же папку, почему не может Java?
В качестве более полного теста я использовал WineMerge на XP, чтобы сравнить дату изменения и размер файлов на сервере с локальными файлами. Это повторялось по всему дереву каталогов из 33 000 файлов в каждой папке. Общее время 7 секунд. Ява: более 5 минут.
Таким образом, первоначальное утверждение и вопрос от ОП верны и действительны. Это менее заметно при работе с локальной файловой системой. Локальное сравнение папки с 33 000 элементов занимает 3 секунды в WinMerge и 32 секунды локально в Java. Итак, опять же, Java в сравнении с нативным - это 10-кратное замедление в этих элементарных тестах.
Java 1.6.0_22 (последняя версия), гигабитная локальная сеть и сетевые подключения, ping менее 1 мс (оба в одном коммутаторе)
Ява медленная
источник
Из теста GHad есть несколько проблем, о которых упоминали люди:
1> Как упомянуто BalusC: в этом случае выполняется stream.available ().
Поскольку available () возвращает оценку количества байтов, которые могут быть прочитаны (или пропущены) из этого входного потока без блокировки при следующем вызове метода для этого входного потока.
Итак, 1-й, чтобы удалить URL этот подход.
2> Как отметил StuartH - порядок выполнения теста также влияет на кэш, поэтому устраните его, запустив тест отдельно.
Теперь начните тестирование:
Когда КАНАЛ один запускается один:
Когда ДЛИНА одна бежит одна:
Похоже, что ДЛИНА является победителем здесь:
источник