我需要帮助找出最快的方法来读取每个文件中超过500,000行的大约80个文件,并写入一个主文件,每个输入文件的行作为主列中的列。主文件必须写入文本编辑器,如记事本,而不是Microsoft产品,因为它们无法处理行数。
例如,主文件应如下所示:
File1_Row1,File2_Row1,File3_Row1,...
File1_Row2,File2_Row2,File3_Row2,...
File1_Row3,File2_Row3,File3_Row3,...
等
到目前为止,我尝试了两种解决方案:
有没有人能够以更快的方式阅读这么多大文件?
答案 0 :(得分:5)
最好的方法是打开输入文件,每个输入文件StreamReader
,输出文件StreamWriter
。然后循环浏览每个阅读器并读取一行并将其写入主文件。这样你一次只能加载一行,所以应该有最小的内存压力。我能够在37秒内复制80~500,000行文件。一个例子:
using System;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
class MainClass
{
static string[] fileNames = Enumerable.Range(1, 80).Select(i => string.Format("file{0}.txt", i)).ToArray();
public static void Main(string[] args)
{
var stopwatch = Stopwatch.StartNew();
List<StreamReader> readers = fileNames.Select(f => new StreamReader(f)).ToList();
try
{
using (StreamWriter writer = new StreamWriter("master.txt"))
{
string line = null;
do
{
for(int i = 0; i < readers.Count; i++)
{
if ((line = readers[i].ReadLine()) != null)
{
writer.Write(line);
}
if (i < readers.Count - 1)
writer.Write(",");
}
writer.WriteLine();
} while (line != null);
}
}
finally
{
foreach(var reader in readers)
{
reader.Close();
}
}
Console.WriteLine("Elapsed {0} ms", stopwatch.ElapsedMilliseconds);
}
}
我假设所有输入文件的行数都相同,但是当至少有一个文件为您提供数据时,您应该添加逻辑以保持读取。
答案 1 :(得分:3)
使用Memory Mapped文件似乎适合您。对您的应用程序的内存不施加压力的东西当代在IO操作中保持良好的性能。
此处有完整的文档:Memory-Mapped Files
答案 2 :(得分:3)
如果计算机上有足够的内存,我会使用Parallel.Invoke构造并将每个文件读入预先分配的数组,例如:
string[] file1lines = new string[some value];
string[] file2lines = new string[some value];
string[] file3lines = new string[some value];
Parallel.Invoke(
() =>
{
ReadMyFile(file1,file1lines);
},
() =>
{
ReadMyFile(file2,file2lines);
},
() =>
{
ReadMyFile(file3,file3lines);
}
);
每个ReadMyFile方法应该使用以下示例代码,according to these benchmarks是最快的方式来读取文本文件:
int x = 0;
using (StreamReader sr = File.OpenText(fileName))
{
while ((file1lines[x] = sr.ReadLine()) != null)
{
x += 1;
}
}
如果您需要在编写最终输出之前操作每个文件中的数据,read this article以最快的方式执行此操作。
然后你只需要一种方法将内容写入每个字符串[]到你想要的输出。
答案 3 :(得分:0)
有一组打开的文件句柄。循环遍历此数组并从每个文件中读取一行到字符串数组中。然后将此数组合并到主文件中,在最后添加换行符。
这与你的第二种方法不同,它是单线程的,不会读取特定的行,但总是下一行。
当然,如果文件的行数少于其他文件,则需要进行错误验证。