сортировка строк огромного файла.txt в java

Я работаю с очень большим текстовым файлом (755Mb). Мне нужно отсортировать строки (около 1890000), а затем записать их обратно в другой файл.

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

проблема в том, что я не могу хранить строки в коллекции в памяти, потому что я получаю исключение кучи Java (даже если я расширил его максимум)..(уже пытался!)

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

Я думал об использовании DB ..но я думаю, что написание всех строк затем использует запрос SELECT, это слишком долго с точки зрения времени выполнения..я ошибаюсь?

какие-то намеки оценили Заранее спасибо

6 ответов


Я думаю, что решение здесь состоит в том, чтобы сделать сортировку слияния с использованием временных файлов:

  1. читать "первый"!--7-->n строки первого файла, (n количество строк, которые вы можете позволить себе хранить и сортировать в памяти), сортировать их и записывать в файл 1.tmp (или как вы это называете). Сделайте то же самое со следующим n строки и хранить его в 2.tmp. Повторяйте, пока все строки исходного файла обработанный.

  2. прочитал первую строку каждого временного файла. Определите наименьший (в соответствии с порядком сортировки), запишите его в файл назначения и прочитайте следующую строку из соответствующего временного файла. Повторяйте, пока все строки не будут обработаны.

  3. удалить все временные файлы.

это работает с произвольными большими файлами, если у вас достаточно места на диске.


вы можете запустить следующее С

-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 памяти.

  1. разделите файл на K чанки, где X * K = 2 GB. Каждый кусок в память и отсортировать строки, как обычно, используя любой . Сохраните строки обратно в файл.

  2. теперь принесите следующий кусок в память и сортировать.

  3. как только мы закончим, объедините их по одному один.

этот алгоритм также известен как внешнего вида. Шаг 3 известен как N-way merge


разделяй и властвуй является лучшим решением :)

разделите файл на более мелкие, отсортируйте каждый файл отдельно, затем перегруппируйте.

ссылки:

сортировка файла с огромным объемом данных с учетом ограничения памяти

http://hackerne.ws/item?id=1603381


Почему бы вам не попробовать многопоточность и увеличение размера кучи запущенной программы? (для этого также требуется использовать сортировку слиянием при условии, что у вас больше памяти, чем 755mb в вашей системе.)


возможно, вы можете использовать perl для форматирования файла .и загрузить в базу данных, как mysql. это так быстро. и используйте индекс для запроса данных. и запишите в другой файл.

u может установить размер кучи jvm как '- Xms256m-Xmx1024m' .я надеюсь помочь вам .спасибо