Обработка файлов в Java
-
30-09-2019 - |
Вопрос
У меня есть файл размера 2 ГБ, в котором есть записи студентов. Мне нужно найти студентов на основе определенных атрибутов в каждой записи и создать новый файл с результатами. Порядок отфильтрованных студентов должен быть таким же, как в исходном файле. Какой эффективный и самый быстрый способ сделать это с помощью Java IO API и потоков без проблем с памятью? Размер MAXHEAP для JVM установлен на 512 МБ.
Решение
- 2 ГБ для файла огромно, вы должны пойти на дБ.
- Если вы действительно хотите использовать Java I/O API, затем попробуйте это: Эффективная обработка больших файлов данных с Java и это: Настройка производительности ввода/вывода Java
Другие советы
Какой файл? Текстовый, как CSV?
Самый простой способ - сделать что -то вроде Grep: прочитать строку файла по строке, проанализировать строку, проверить свой критерий фильтра, если они соответствуют, выведите линию результата, затем перейдите к следующей строке, пока файл не будет выполнен. Это очень эффективно память, так как у вас есть только текущая линия (или буфер немного больше), загруженной одновременно. Ваш процесс должен прочитать весь файл только один раз.
Я не думаю, что несколько тем очень помогут. Это сделало бы ситуацию намного сложнее, и, поскольку процесс, кажется, в любом случае связан вводами/выводом, попытка прочитать один и тот же файл с несколькими потоками, вероятно, не улучшает пропускную способность.
Если вы обнаружите, что вам нужно делать это часто, и проходить через файл каждый раз слишком медленно, вам нужно создавать какой -то индекс. Самый простой способ сделать это - импортировать файл в БД (может быть встроенным DB, таким как SQLite или HSQL) в первую очередь.
Я бы не преувеличил бы это, пока вы не обнаружите, что бурно простой способ не работает для того, что вам нужно. По сути, вам просто нужно:
- Открыть поток ввода в файл 2 ГБ, помня Buffer (например, обернув BufferedInputStream)
- Откройте потоки вывода для фильтрованного файла, который вы собираетесь создать
- Прочитайте первую запись из потока ввода, посмотрите на любой атрибут, чтобы решить, нужен ли вам »его; Если вы это сделаете, напишите его в файл вывода
- Повторите для оставшихся записей
В одной из моих тестовых систем с чрезвычайно скромным аппаратным обеспечением, BufferedInputStream вокруг файлового потока из коробки. Прочитав около 500 МБ за 25 секунд, то есть, вероятно, менее 2 минут для обработки вашего файла 2 ГБ, и размер буфера по умолчанию в основном так же хорош, как и он (См BufferedInputStream Timings Я сделал более подробную информацию). Я полагаю, что с современным оборудованием вполне возможно, что время будет вдвое.
Независимо от того, нужно ли вам прийти к большим усилиям, чтобы сократить 2/3 минуты или просто пойти на крошечный, пока вы ждете, когда он запустит, - это решение, которое вам придется принять в зависимости от ваших требований. Я думаю, что вариант базы данных не купит вас много, если вам не нужно будет выполнять множество различных прогонов обработки в одном и том же наборе данных (и есть и другие решения, которые не означают автоматически базу данных).
Я думаю, ты должен использовать Память на карту Файлы. Это поможет вам составить карту более крупного файла с меньшей памятью. Это будет действовать как виртуальная память, и что касается производительности. Сопоставленные файлы более быстрее, чем потоковая запись/чтение.