2010-08-20 3 views
1

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

+2

Рассмотрите возможность хранения информации в базе данных, а не в файле размером 2 ГБ. Сделайте это для студентов. База данных – polygenelubricants

+0

не является для меня вариантом. Я получу данные в текстовых файлах, и я должен обработать их. –

+0

Невозможно получить X фунтов всего в сумке X/N, где N> 1. Вы никогда не сжимаете все содержимое этого файла в память сразу без сжатия. – duffymo

ответ

6

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

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

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

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

+0

О, мальчик, я печатал точно такой же ответ. Это действительно все сводится к тому, чтобы делать работу просто по строкам, а не хранить все это в памяти Java. – BalusC

5

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

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

На одном из моих тестовых систем с очень скромным оборудованием, BufferedInputStream вокруг FileInputStream из коробки прочитать около 500 МБ в течение 25 секунд, т.е. вероятно, менее 2 минут для обработки вашего 2GB-файла, а размер буфера по умолчанию в основном такой же хороший, как и он (см. BufferedInputStream timings, который я сделал для получения дополнительной информации). Я предполагаю, что с современными аппаратными средствами вполне возможно, что время будет сокращено наполовину.

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

+0

+1, особенно. за то, что «пойдите на крошечку, пока вы ждете» –

0

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

Смежные вопросы