Мне нужно прочитать большой текстовый файл, скажем, 25 ГБ, и мне нужно обработать этот файл в течение 15-20 минут. Этот файл будет иметь несколько разделов верхнего и нижнего колонтитула.
Я попытался разбить этот файл с помощью CSplit на основе заголовка, но разделение его на несколько файлов на основе заголовка занимает от 24 до 25 минут, что совершенно неприемлемо.
Я пробовал последовательное чтение и запись, используя BufferReader
и BufferWiter
вместе с FileReader
и FileWriter
. Идет более 27 мин. Опять же, это неприемлемо.
Я попробовал другой подход, например получить начальный индекс каждого заголовка, а затем запустить несколько потоков для чтения файла из определенного места с помощью RandomAccessFile
. Но в этом не повезло.
Как я могу достичь своего требования?
Возможный дубликат:
4 ответа
Попробуйте использовать большой размер буфера для чтения (например, 20 МБ вместо 2 МБ), чтобы быстрее обрабатывать данные. Также не используйте BufferedReader из-за низкой скорости и преобразования символов.
Этот вопрос задавался раньше: Чтение больших файлов в Java
Вы должны убедиться, что ввод-вывод выполняется достаточно быстро без вашей обработки, потому что я подозреваю, что обработка, а не ввод-вывод замедляет вас. Вы должны быть в состоянии получить 80 МБ/с с жесткого диска и до 400 МБ/с с SSD-накопителя. Это означает, что вы можете прочитать все за одну секунду.
Попробуйте следующее, не самое быстрое, но самое простое.
long start = System.nanoTime();
byte[] bytes = new byte[32*1024];
FileInputStream fis = new FileInputStream(fileName);
int len;
while((len = fis.read(bytes)) > 0);
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds%n", time/1e9);
Если вы не обнаружите, что получаете не менее 50 МБ/с, у вас проблема с оборудованием.
Попробуйте использовать java.nio
, чтобы лучше использовать функциональные возможности операционной системы. Избегайте копирования данных (например, в строку), но попробуйте работать с смещениями. Я полагаю, что классы java.nio будут даже иметь методы для передачи данных из одного буфера в другой, вообще не загружая данные на уровень java (по крайней мере, в Linux), но это по существу будет переводиться в вызовы операционной системы.
Для многих современных веб-серверов этот метод был ключом к производительности, с которой они могут обслуживать статические данные: по сути, они делегируют как можно больше операционной системе, чтобы избежать их дублирования в основной памяти.
Позвольте мне подчеркнуть это: просто поиск в буфере байтов размером 25 ГБ намного быстрее, чем преобразование его в строки Java (для чего может потребоваться кодирование/декодирование набора символов и копирование). Все, что сохраняет копии и управление памятью, поможет.
Если платформа подходит, вы можете захотеть раскошелиться и вызвать комбинацию cat и sed. Если это не так, вы все равно можете раскошелиться и использовать perl через командную строку. В случае, когда фактическая обработка обязательно должна выполняться Java, другие предоставили достаточно ответов.
Однако будьте начеку, раскошелиться не без проблем. Но perl или sed могут быть единственными широко доступными инструментами для сканирования и изменения 25 ГБ текста за ваш период времени.
Похожие вопросы
Связанные вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.
int
. У вас есть другое решение, чтобы предложить?