сортировка строк огромного файла.txt в java
Я работаю с очень большим текстовым файлом (755Mb). Мне нужно отсортировать строки (около 1890000), а затем записать их обратно в другой файл.
Я уже заметил, что обсуждение, которое имеет начальный файл, очень похоже на мое: сортировка строк на основе слов в них в качестве ключей
проблема в том, что я не могу хранить строки в коллекции в памяти, потому что я получаю исключение кучи Java (даже если я расширил его максимум)..(уже пытался!)
Я не могу открыть его с помощью excel и использовать функцию сортировки, потому что файл слишком велик и не может быть полностью загружен..
Я думал об использовании DB ..но я думаю, что написание всех строк затем использует запрос SELECT, это слишком долго с точки зрения времени выполнения..я ошибаюсь?
какие-то намеки оценили Заранее спасибо
6 ответов
Я думаю, что решение здесь состоит в том, чтобы сделать сортировку слияния с использованием временных файлов:
читать "первый"!--7-->n строки первого файла, (n количество строк, которые вы можете позволить себе хранить и сортировать в памяти), сортировать их и записывать в файл
1.tmp
(или как вы это называете). Сделайте то же самое со следующим n строки и хранить его в2.tmp
. Повторяйте, пока все строки исходного файла обработанный.прочитал первую строку каждого временного файла. Определите наименьший (в соответствии с порядком сортировки), запишите его в файл назначения и прочитайте следующую строку из соответствующего временного файла. Повторяйте, пока все строки не будут обработаны.
удалить все временные файлы.
это работает с произвольными большими файлами, если у вас достаточно места на диске.
вы можете запустить следующее С
-mx1g -XX:+UseCompressedStrings # on Java 6 update 29
-mx1800m -XX:-UseCompressedStrings # on Java 6 update 29
-mx2g # on Java 7 update 2.
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String... args) throws IOException {
long start = System.nanoTime();
generateFile("lines.txt", 755 * 1024 * 1024, 189000);
List<String> lines = loadLines("lines.txt");
System.out.println("Sorting file");
Collections.sort(lines);
System.out.println("... Sorted file");
// save lines.
long time = System.nanoTime() - start;
System.out.printf("Took %.3f second to read, sort and write to a file%n", time / 1e9);
}
private static void generateFile(String fileName, int size, int lines) throws FileNotFoundException {
System.out.println("Creating file to load");
int lineSize = size / lines;
StringBuilder sb = new StringBuilder();
while (sb.length() < lineSize) sb.append('-');
String padding = sb.toString();
PrintWriter pw = new PrintWriter(fileName);
for (int i = 0; i < lines; i++) {
String text = (i + padding).substring(0, lineSize);
pw.println(text);
}
pw.close();
System.out.println("... Created file to load");
}
private static List<String> loadLines(String fileName) throws IOException {
System.out.println("Reading file");
BufferedReader br = new BufferedReader(new FileReader(fileName));
List<String> ret = new ArrayList<String>();
String line;
while ((line = br.readLine()) != null)
ret.add(line);
System.out.println("... Read file.");
return ret;
}
}
печать
Creating file to load
... Created file to load
Reading file
... Read file.
Sorting file
... Sorted file
Took 4.886 second to read, sort and write to a file
:
сколько памяти у нас? Предположим, у нас есть X MB
памяти.
разделите файл на
K
чанки, гдеX * K = 2 GB
. Каждый кусок в память и отсортировать строки, как обычно, используя любой . Сохраните строки обратно в файл.теперь принесите следующий кусок в память и сортировать.
как только мы закончим, объедините их по одному один.
этот алгоритм также известен как внешнего вида. Шаг 3 известен как N-way merge
разделяй и властвуй является лучшим решением :)
разделите файл на более мелкие, отсортируйте каждый файл отдельно, затем перегруппируйте.
ссылки:
сортировка файла с огромным объемом данных с учетом ограничения памяти
Почему бы вам не попробовать многопоточность и увеличение размера кучи запущенной программы? (для этого также требуется использовать сортировку слиянием при условии, что у вас больше памяти, чем 755mb в вашей системе.)
возможно, вы можете использовать perl для форматирования файла .и загрузить в базу данных, как mysql. это так быстро. и используйте индекс для запроса данных. и запишите в другой файл.
u может установить размер кучи jvm как '- Xms256m-Xmx1024m' .я надеюсь помочь вам .спасибо