Мне нужно прочитать большой текстовый файл, скажем, 25 ГБ, и мне нужно обработать этот файл в течение 15-20 минут. Этот файл будет иметь несколько разделов верхнего и нижнего колонтитула.

Я попытался разбить этот файл с помощью CSplit на основе заголовка, но разделение его на несколько файлов на основе заголовка занимает от 24 до 25 минут, что совершенно неприемлемо.

Я пробовал последовательное чтение и запись, используя BufferReader и BufferWiter вместе с FileReader и FileWriter. Идет более 27 мин. Опять же, это неприемлемо.

Я попробовал другой подход, например получить начальный индекс каждого заголовка, а затем запустить несколько потоков для чтения файла из определенного места с помощью RandomAccessFile. Но в этом не повезло.

Как я могу достичь своего требования?

Возможный дубликат:

Чтение больших файлов на Java

10
user1142292 11 Янв 2012 в 08:03

4 ответа

Попробуйте использовать большой размер буфера для чтения (например, 20 МБ вместо 2 МБ), чтобы быстрее обрабатывать данные. Также не используйте BufferedReader из-за низкой скорости и преобразования символов.

Этот вопрос задавался раньше: Чтение больших файлов в Java

9
Community 23 Май 2017 в 14:45

Вы должны убедиться, что ввод-вывод выполняется достаточно быстро без вашей обработки, потому что я подозреваю, что обработка, а не ввод-вывод замедляет вас. Вы должны быть в состоянии получить 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 МБ/с, у вас проблема с оборудованием.

6
Peter Lawrey 11 Янв 2012 в 11:40

Попробуйте использовать java.nio, чтобы лучше использовать функциональные возможности операционной системы. Избегайте копирования данных (например, в строку), но попробуйте работать с смещениями. Я полагаю, что классы java.nio будут даже иметь методы для передачи данных из одного буфера в другой, вообще не загружая данные на уровень java (по крайней мере, в Linux), но это по существу будет переводиться в вызовы операционной системы.

Для многих современных веб-серверов этот метод был ключом к производительности, с которой они могут обслуживать статические данные: по сути, они делегируют как можно больше операционной системе, чтобы избежать их дублирования в основной памяти.

Позвольте мне подчеркнуть это: просто поиск в буфере байтов размером 25 ГБ намного быстрее, чем преобразование его в строки Java (для чего может потребоваться кодирование/декодирование набора символов и копирование). Все, что сохраняет копии и управление памятью, поможет.

1
Has QUIT--Anony-Mousse 11 Янв 2012 в 11:26
3
NIO имеет свои собственные уродливые ограничения, встроенные прямо в него: в лучшем случае вы можете отобразить 2 ГБ в качестве буфера, поскольку Buffer API использует целое число для всех смещений. Это делает nio в лучшем случае громоздким для больших файлов.
 – 
Durandal
11 Янв 2012 в 15:27
Я также сталкиваюсь с проблемой, когда это смещение принимается как int. У вас есть другое решение, чтобы предложить?
 – 
Mohammad Faisal
25 Ноя 2021 в 10:02

Если платформа подходит, вы можете захотеть раскошелиться и вызвать комбинацию cat и sed. Если это не так, вы все равно можете раскошелиться и использовать perl через командную строку. В случае, когда фактическая обработка обязательно должна выполняться Java, другие предоставили достаточно ответов.

Однако будьте начеку, раскошелиться не без проблем. Но perl или sed могут быть единственными широко доступными инструментами для сканирования и изменения 25 ГБ текста за ваш период времени.

1
0xCAFEBABE 11 Янв 2012 в 11:45