我只需要N个已经排序的磁盘上的文件的Merge功能, 我想将它们分成一个大文件我的限制是内存不超过内存中的K行(K<n)所以我无法获取所有它们然后排序,首选java public void run() {
try {
System.out.println(file1 " Started Merging " file2 );
FileReader fileReader1 = new FileReader(file1);
FileReader fileReader2 = new FileReader(file2);
//......TODO with N ?? ......
FileWriter writer = new FileWriter(file3);
BufferedReader bufferedReader1 = new BufferedReader(fileReader1);
BufferedReader bufferedReader2 = new BufferedReader(fileReader2);
String line1 = bufferedReader1.readLine();
String line2 = bufferedReader2.readLine();
//Merge 2 files based on which string is greater.
while (line1 != null || line2 != null) {
if (line1 == null || (line2 != null && line1.compareTo(line2) > 0)) {
writer.write(line2 "\r\n");
line2 = bufferedReader2.readLine();
} else {
writer.write(line1 "\r\n");
line1 = bufferedReader1.readLine();
}
}
System.out.println(file1 " Done Merging " file2 );
new File(file1).delete();
new File(file2).delete();
writer.close();
} catch (Exception e) {
System.out.println(e);
}
}
问候,
解决方法: 你可以使用这样的东西 public static void mergeFiles(String target, String... input) throws IOException {
String lineBreak = System.getProperty("line.separator");
PriorityQueue<Map.Entry<String,BufferedReader>> lines
= new PriorityQueue<>(Map.Entry.comparingByKey());
try(FileWriter fw = new FileWriter(target)) {
String header = null;
for(String file: input) {
BufferedReader br = new BufferedReader(new FileReader(file));
String line = br.readLine();
if(line == null) br.close();
else {
if(header == null) fw.append(header = line).write(lineBreak);
line = br.readLine();
if(line != null) lines.add(new AbstractMap.SimpleImmutableEntry<>(line, br));
else br.close();
}
}
for(;;) {
Map.Entry<String, BufferedReader> next = lines.poll();
if(next == null) break;
fw.append(next.getKey()).write(lineBreak);
final BufferedReader br = next.getValue();
String line = br.readLine();
if(line != null) lines.add(new AbstractMap.SimpleImmutableEntry<>(line, br));
else br.close();
}
}
catch(Throwable t) {
for(Map.Entry<String,BufferedReader> br: lines) try {
br.getValue().close();
} catch(Throwable next) {
if(t != next) t.addSuppressed(next);
}
}
}
请注意,与您的问题中的代码不同,此代码处理标题行.与原始代码一样,它将删除输入行.如果不是这样,您可以删除DELETE_ON_CLOSE选项并简化整个阅读器构造 BufferedReader br = new BufferedReader(new FileReader(file)); 它拥有与文件一样多的内存行. 原则上,可以在内存中保留较少的线串,在需要时重新读取它们,这对于可疑的少量保存来说将是性能灾难.例如.由于您有N个文件名,因此在调用此方法时,您在内存中已经有N个字符串. 但是,当您想要不惜一切代价减少同时保留的行数时,您只需使用问题中显示的方法即可.将前两个文件合并到一个临时文件中,将该临时文件与第三个文件合并到另一个临时文件,依此类推,直到将临时文件与最后一个输入文件合并到最终结果.然后你在内存中最多有两个线串(K == 2),比操作系统用于缓冲的内存节省更少,试图减轻这种方法的可怕性能. 同样,您可以使用上面显示的方法将K文件合并到一个临时文件中,然后将临时文件与下一个K-1文件合并,依此类推,直到将临时文件与剩余的K-1或更少文件合并为止最终结果是,在K <1的情况下进行存储器消耗缩放. N.这种方法允许调整K以使其具有合理的N比率,以便将速度换成记忆.我认为,在大多数实际情况中,K == N将会正常工作.
|