Мне нужно читать большой текстовый файл размером около 5-6 ГБ построчно, используя Java.
Как я могу сделать это быстро?
java
performance
file-io
io
garbage-collection
Манодж Сингх
источник
источник
Ответы:
Распространенным примером является использование
Вы можете читать данные быстрее, если предположите, что кодировка символов отсутствует. например, ASCII-7, но это не будет иметь большого значения. Весьма вероятно, что то, что вы будете делать с данными, займет гораздо больше времени.
РЕДАКТИРОВАТЬ: менее распространенный шаблон, который позволяет избежать
line
утечки.ОБНОВЛЕНИЕ: в Java 8 вы можете сделать
ПРИМЕЧАНИЕ. Вы должны поместить Stream в блок try-with-resource, чтобы убедиться, что для него вызывается метод #close, иначе основной дескриптор файла никогда не будет закрыт, пока GC не сделает это намного позже.
источник
for(String line = br.readLine(); line != null; line = br.readLine())
, в Java 8 вы можете сделать,try( Stream<String> lines = Files.lines(...) ){ for( String line : (Iterable<String>) lines::iterator ) { ... } }
что трудно не ненавидеть.Посмотрите на этот блог:
источник
DataInputStream
, а не тот поток закрыт. Ничего плохого в Java Tutorial, и нет необходимости цитировать произвольный сторонний мусор в Интернете, как этот.После выхода Java 8 (март 2014 года) вы сможете использовать потоки:
Печать всех строк в файле:
источник
StandardCharsets.UTF_8
, используйтеStream<String>
для краткости, и избегайте использования,forEach()
и особенноforEachOrdered()
если нет причины.forEach(this::process)
, но становится уродливым, если вы пишете блоки кода как лямбды внутриforEach()
.forEachOrdered
для того чтобы выполнить по порядку. Имейте в виду, что в этом случае вы не сможете распараллелить поток, хотя я обнаружил, что распараллеливание не включается, если в файле нет тысяч строк.Вот пример с полной обработкой ошибок и поддержкой спецификации кодировки для pre-Java 7. В Java 7 вы можете использовать синтаксис try-with-resources, который делает код чище.
Если вы просто хотите использовать кодировку по умолчанию, вы можете пропустить InputStream и использовать FileReader.
Вот Groovy-версия с полной обработкой ошибок:
источник
ByteArrayInputStream
поступает строковый литерал с чтением большого текстового файла?В Java 8 вы можете сделать:
Некоторые примечания: поток, возвращаемый
Files.lines
(в отличие от большинства потоков), должен быть закрыт. По причинам, указанным здесь, я избегаю использованияforEach()
. Странный код(Iterable<String>) lines::iterator
переводит поток в Iterable.источник
Iterable
этого кода определенно уродлив, хотя и полезен. Это нуждается в броске (то есть(Iterable<String>)
), чтобы работать.for(String line : (Iterable<String>) lines.skip(1)::iterator)
Stream
функции, используяFiles.newBufferedReader
вместоFiles.lines
и повторяющегося вызова ,readLine()
покаnull
вместо того , чтобы использовать конструкции , как ,(Iterable<String>) lines::iterator
кажется, гораздо проще ...Что вы можете сделать, это отсканировать весь текст с помощью сканера и проходить текст построчно. Конечно, вы должны импортировать следующее:
Сканер в основном сканирует весь текст. Цикл while используется для перемещения по всему тексту.
.hasNextLine()
Функция булева , которая возвращает истину , если есть еще несколько строк в тексте..nextLine()
Функция дает Вам всю строку в виде строки , которые вы можете использовать, как вы хотите. ПытатьсяSystem.out.println(line)
напечатать текст.Примечание: .txt - это текст типа файла.
источник
BufferedReader.readLine()
, и он попросил самый эффективный метод.FileReader не позволит вам указать кодировку, используйте
InputStreamReader
вместо этого, если вам нужно указать ее:Если вы импортировали этот файл из Windows, он может иметь кодировку ANSI (Cp1252), поэтому вам необходимо указать кодировку.
источник
Я задокументировал и протестировал 10 различных способов чтения файлов на Java, а затем сопоставил их друг с другом, заставив их читать в тестовых файлах от 1 КБ до 1 ГБ. Вот самые быстрые 3 метода чтения файлов для чтения тестового файла объемом 1 ГБ.
Обратите внимание, что при выполнении тестов производительности я ничего не выводил на консоль, поскольку это действительно замедляло бы тестирование. Я просто хотел проверить скорость чтения.
1) java.nio.file.Files.readAllBytes ()
Протестировано в Java 7, 8, 9. В целом это был самый быстрый метод. Чтение файла объемом 1 ГБ всегда было менее 1 секунды.
2) java.nio.file.Files.lines ()
Это было успешно протестировано в Java 8 и 9, но не будет работать в Java 7 из-за отсутствия поддержки лямбда-выражений. Чтение файла размером 1 ГБ заняло около 3,5 секунд, что ставит его на второе место после чтения больших файлов.
3) BufferedReader
Проверено на работу в Java 7, 8, 9. Для считывания тестового файла объемом 1 ГБ потребовалось около 4,5 секунд.
Вы можете найти полный рейтинг всех 10 методов чтения файлов здесь .
источник
System.out.print/println()
здесь; вы также предполагаете, что файл поместится в память в первых двух случаях.В Java 7:
источник
StandardCharsets.UTF_8
чтобы избежать проверенного исключения вCharset.forName("UTF-8")
В Java 8 также есть альтернатива использованию
Files.lines()
. Если ваш входной источник не файл, а что-то более абстрактное, например aReader
или anInputStream
, вы можете передавать строки с помощью методаBufferedReader
slines()
.Например:
будет вызывать
processLine()
для каждой строки ввода, прочитаннойBufferedReader
.источник
Для чтения файла с Java 8
источник
Вы можете использовать класс сканера
источник
Scanner
это хорошо, но этот ответ не включает полный код, чтобы использовать его правильно.BufferedReader.readLine()
, безусловно, в несколько раз быстрее. Если вы думаете иначе, пожалуйста, укажите ваши причины.Вам нужно использовать
readLine()
метод вclass BufferedReader
. Создайте новый объект из этого класса, примените этот метод к нему и сохраните его в строку.BufferReader Javadoc
источник
Четкий способ достичь этого,
Например:
Если у вас есть
dataFile.txt
в вашем текущем каталогеВывод, как показано ниже,
источник
Java 9:
источник
System.getProperty("os.name").equals("Linux")
==
!Меня устраивает. Надеюсь, это вам тоже поможет.
источник
Вы можете использовать потоки, чтобы сделать это более точно:
источник
Я обычно делаю рутину чтения просто:
источник
Вы можете использовать этот код:
источник
Использование пакета org.apache.commons.io позволило повысить производительность, особенно в устаревшем коде, который использует Java 6 и ниже.
Java 7 имеет лучший API с меньшим количеством обработок исключений и более полезными методами:
специалист
источник
Вы также можете использовать Apache Commons IO :
источник
FileUtils.readLines(file)
является устаревшим методом. Кроме того, метод вызываетIOUtils.readLines
, который использует BufferedReader и ArrayList. Это не построчный метод, и, конечно, он не подходит для чтения нескольких ГБ.