Вопрос

У меня есть файл размера 2 ГБ, в котором есть записи студентов. Мне нужно найти студентов на основе определенных атрибутов в каждой записи и создать новый файл с результатами. Порядок отфильтрованных студентов должен быть таким же, как в исходном файле. Какой эффективный и самый быстрый способ сделать это с помощью Java IO API и потоков без проблем с памятью? Размер MAXHEAP для JVM установлен на 512 МБ.

Это было полезно?

Решение

  1. 2 ГБ для файла огромно, вы должны пойти на дБ.
  2. Если вы действительно хотите использовать Java I/O API, затем попробуйте это: Эффективная обработка больших файлов данных с Java и это: Настройка производительности ввода/вывода Java

Другие советы

Какой файл? Текстовый, как CSV?

Самый простой способ - сделать что -то вроде Grep: прочитать строку файла по строке, проанализировать строку, проверить свой критерий фильтра, если они соответствуют, выведите линию результата, затем перейдите к следующей строке, пока файл не будет выполнен. Это очень эффективно память, так как у вас есть только текущая линия (или буфер немного больше), загруженной одновременно. Ваш процесс должен прочитать весь файл только один раз.

Я не думаю, что несколько тем очень помогут. Это сделало бы ситуацию намного сложнее, и, поскольку процесс, кажется, в любом случае связан вводами/выводом, попытка прочитать один и тот же файл с несколькими потоками, вероятно, не улучшает пропускную способность.

Если вы обнаружите, что вам нужно делать это часто, и проходить через файл каждый раз слишком медленно, вам нужно создавать какой -то индекс. Самый простой способ сделать это - импортировать файл в БД (может быть встроенным DB, таким как SQLite или HSQL) в первую очередь.

Я бы не преувеличил бы это, пока вы не обнаружите, что бурно простой способ не работает для того, что вам нужно. По сути, вам просто нужно:

  • Открыть поток ввода в файл 2 ГБ, помня Buffer (например, обернув BufferedInputStream)
  • Откройте потоки вывода для фильтрованного файла, который вы собираетесь создать
  • Прочитайте первую запись из потока ввода, посмотрите на любой атрибут, чтобы решить, нужен ли вам »его; Если вы это сделаете, напишите его в файл вывода
  • Повторите для оставшихся записей

В одной из моих тестовых систем с чрезвычайно скромным аппаратным обеспечением, BufferedInputStream вокруг файлового потока из коробки. Прочитав около 500 МБ за 25 секунд, то есть, вероятно, менее 2 минут для обработки вашего файла 2 ГБ, и размер буфера по умолчанию в основном так же хорош, как и он (См BufferedInputStream Timings Я сделал более подробную информацию). Я полагаю, что с современным оборудованием вполне возможно, что время будет вдвое.

Независимо от того, нужно ли вам прийти к большим усилиям, чтобы сократить 2/3 минуты или просто пойти на крошечный, пока вы ждете, когда он запустит, - это решение, которое вам придется принять в зависимости от ваших требований. Я думаю, что вариант базы данных не купит вас много, если вам не нужно будет выполнять множество различных прогонов обработки в одном и том же наборе данных (и есть и другие решения, которые не означают автоматически базу данных).

Я думаю, ты должен использовать Память на карту Файлы. Это поможет вам составить карту более крупного файла с меньшей памятью. Это будет действовать как виртуальная память, и что касается производительности. Сопоставленные файлы более быстрее, чем потоковая запись/чтение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top