我正在处理一个非常大的文本文件(755Mb)。 我需要对行进行排序(大约1890000),然后将它们写回另一个文件中。
我已经注意到有一个起始文件的讨论与我的相似: Sorting Lines Based on words in them as keys
问题是我无法将行存储在内存中的集合中,因为我得到了Java堆空间异常(即使我最大限度地扩展它)..(已经尝试过!)
我无法使用excel打开它并使用排序功能,因为文件太大而且无法完全加载..
我考虑过使用数据库..但我认为编写所有行然后使用SELECT查询它在执行时间方面太长了......我错了吗?
任何提示都表示赞赏 提前致谢
答案 0 :(得分:15)
我认为这里的解决方案是使用临时文件进行合并排序:
读取第一个文件的第一行 n 行( n 是您可以在内存中存储和排序的行数),对它们进行排序,并将它们写入文件1.tmp
(或者你称之为)。对下一个 n 行执行相同操作并将其存储在2.tmp
中。重复,直到处理完原始文件的所有行。
读取每个临时文件的第一行。确定最小的一个(根据您的排序顺序),将其写入目标文件,并从相应的临时文件中读取下一行。重复,直到所有行都已处理完毕。
删除所有临时文件。
只要你有足够的磁盘空间,这适用于任意大文件。
答案 1 :(得分:2)
您可以使用
运行以下命令-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
答案 2 :(得分:1)
算法:
我们有多少内存?假设我们有X MB
个可用内存。
将文件分为K
块,其中X * K = 2 GB
。将每个块放入内存并使用任何O(n log n)
算法对行进行排序。将行保存回文件。
现在将下一个块带入内存并排序。
完成后,请逐一合并。
上述算法也称为外部排序。第3步称为 N-way merge
答案 3 :(得分:0)
为什么不尝试多线程并增加正在运行的程序的堆大小? (这也要求你使用合并排序类的东西,只要你的系统中有超过755mb的内存。)
答案 4 :(得分:0)
divide and conquer是最佳解决方案:)
将文件分成较小的文件,单独对每个文件进行排序,然后重新组合。
链接:
Sort a file with huge volume of data given memory constraint
答案 5 :(得分:-2)
也许你可以使用perl来格式化文件。并像mysql一样加载到数据库中。它太快了。并使用索引来查询数据。并写入另一个文件。
你可以设置jvm堆大小,比如'-Xms256m -Xmx1024m'。我希望能帮助你。谢谢