所以我有成对的大文件(大约4演出)txt文件,我需要创建一个第3个文件,其中包含shuffle模式下的2个文件。以下等式表示最佳:
3rdfile =(文件1中的4行)+(文件2中的4行)并重复此操作直到我到达文件1的末尾(两个输入文件将具有相同的长度 - 这是根据定义)。这是我现在使用的代码,但这在大文件上的扩展性不是很好。我想知道是否有更有效的方法来执行此操作 - 是否可以使用内存映射文件帮助?欢迎所有的想法。
public static void mergeFastq(String forwardFile, String reverseFile, String outputFile) {
try {
BufferedReader inputReaderForward = new BufferedReader(new FileReader(forwardFile));
BufferedReader inputReaderReverse = new BufferedReader(new FileReader(reverseFile));
PrintWriter outputWriter = new PrintWriter(new FileWriter(outputFile, true));
String forwardLine = null;
System.out.println("Begin merging Fastq files");
int readsMerge = 0;
while ((forwardLine = inputReaderForward.readLine()) != null) {
//append the forward file
outputWriter.println(forwardLine);
outputWriter.println(inputReaderForward.readLine());
outputWriter.println(inputReaderForward.readLine());
outputWriter.println(inputReaderForward.readLine());
//append the reverse file
outputWriter.println(inputReaderReverse.readLine());
outputWriter.println(inputReaderReverse.readLine());
outputWriter.println(inputReaderReverse.readLine());
outputWriter.println(inputReaderReverse.readLine());
readsMerge++;
if(readsMerge % 10000 == 0) {
System.out.println("[" + now() + "] Merged 10000");
readsMerge = 0;
}
}
inputReaderForward.close();
inputReaderReverse.close();
outputWriter.close();
} catch (IOException ex) {
Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, "Error while merging FastQ files", ex);
}
}
答案 0 :(得分:2)
也许您还想尝试使用BufferedWriter来减少文件IO操作。 http://download.oracle.com/javase/6/docs/api/java/io/BufferedWriter.html
答案 1 :(得分:0)
一个简单的答案是使用更大的缓冲区,这有助于减少正在进行的I / O调用总数。
通常,使用FileChannel(请参阅Java NIO)的内存映射IO将用于处理大型数据文件IO。但是,在这种情况下,情况并非如此,因为您需要检查文件内容以确定每4行的边界。
答案 2 :(得分:0)
缓冲您的读写操作。缓冲区需要足够大,以最大限度地减少读/写操作,并保持内存效率。这很简单,很有效。
void write(InputStream is, OutputStream os) throws IOException {
byte[] buf = new byte[102400]; //optimize the size of buffer to your needs
int num;
while((n = is.read(buf)) != -1){
os.write(buffer, 0, num);
}
}
编辑: 我刚刚意识到你需要对这些行进行洗牌,所以这段代码不适合你,但概念仍然保持不变。
答案 3 :(得分:0)
如果性能是主要要求,那么我将用C或C ++代替Java来编写这个函数。
但无论使用何种语言,我要做的就是尝试自己管理记忆。我会创建两个大缓冲区,比如128MB或更多,并用两个文本文件中的数据填充它们。然后你需要一个比前两个大两倍的第三个缓冲区。该算法将开始从输入缓冲区#1逐个移动字符到目标缓冲区,同时计算EOL。到达第4行后,将当前位置存储在该缓冲区上,并使用第2个输入缓冲区重复相同的过程。您继续在两个输入缓冲区之间交替,在消耗缓冲区中的所有数据时补充缓冲区。每次必须重新填充输入缓冲区时,您还可以编写目标缓冲区并清空它。