我有超过125个TSV文件,每个我想要合并约100Mb。合并操作允许销毁125个文件,但不能销毁数据。什么事情是最后,我最终得到一个接一个的所有文件的内容的大文件(没有特定的顺序)。
有没有一种有效的方法呢?我想知道Windows是否提供了一个API来简单地创建所有这些文件的大“联盟”?否则,我将不得不阅读所有文件并写一个大文件。
谢谢!
答案 0 :(得分:17)
所以“合并”实际上只是一个接一个地写文件?这非常简单 - 只需打开一个输出流,然后重复打开输入流,复制数据,关闭。例如:
static void ConcatenateFiles(string outputFile, params string[] inputFiles)
{
using (Stream output = File.OpenWrite(outputFile))
{
foreach (string inputFile in inputFiles)
{
using (Stream input = File.OpenRead(inputFile))
{
input.CopyTo(output);
}
}
}
}
那是使用.NET 4中新增的Stream.CopyTo
方法。如果你不使用.NET 4,另一个帮助方法会派上用场:
private static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
我所知道的没有什么比这更有效......但重要的是,这根本不会占用你系统的大量内存。这并不是说它反复将整个文件读入内存然后再写出来。
编辑:正如评论中所指出的,有些方法可以将文件选项摆弄到潜在的,使其在文件系统对数据的作用方面稍微提高效率。但从根本上说,无论哪种方式,你都会读取数据并一次写入缓冲区。
答案 1 :(得分:2)
从命令行执行此操作:
copy 1.txt+2.txt+3.txt combined.txt
或
copy *.txt combined.txt
答案 2 :(得分:2)
你的意思是 merge 你想用一些自定义逻辑决定哪些行去哪里?或者你的意思是你主要想把文件连成一个大文件?
对于后者,您可能根本不需要以编程方式执行此操作,只需生成一个批处理文件(/b
表示二进制,如果不需要则删除):< / p>
copy /b "file 1.tsv" + "file 2.tsv" "destination file.tsv"
使用C#,我采取以下方法。编写一个复制两个流的简单函数:
void CopyStreamToStream(Stream dest, Stream src)
{
int bytesRead;
// experiment with the best buffer size, often 65536 is very performant
byte[] buffer = new byte[GOOD_BUFFER_SIZE];
// copy everything
while((bytesRead = src.Read(buffer, 0, buffer.Length)) > 0)
{
dest.Write(buffer, 0, bytesRead);
}
}
// then use as follows (do in a loop, don't forget to use using-blocks)
CopStreamtoStream(yourOutputStream, yourInputStream);
答案 3 :(得分:0)
你为什么要这样做?
一种方法可能是摆弄低级碎片,如果你让它工作就会很酷。
这是C#的包装器。
http://blogs.msdn.com/b/jeffrey_wall/archive/2004/09/13/229137.aspx
答案 4 :(得分:0)
使用一个100MB的文本文件文件夹,总计约12GB,我发现通过使用File.ReadAllBytes
,然后将其写到流中,可以在可接受的答案上节省一些时间。
[Test]
public void RaceFileMerges()
{
var inputFilesPath = @"D:\InputFiles";
var inputFiles = Directory.EnumerateFiles(inputFilesPath).ToArray();
var sw = new Stopwatch();
sw.Start();
ConcatenateFilesUsingReadAllBytes(@"D:\ReadAllBytesResult", inputFiles);
Console.WriteLine($"ReadAllBytes method in {sw.Elapsed}");
sw.Reset();
sw.Start();
ConcatenateFiles(@"D:\CopyToResult", inputFiles);
Console.WriteLine($"CopyTo method in {sw.Elapsed}");
}
private static void ConcatenateFiles(string outputFile, params string[] inputFiles)
{
using (var output = File.OpenWrite(outputFile))
{
foreach (var inputFile in inputFiles)
{
using (var input = File.OpenRead(inputFile))
{
input.CopyTo(output);
}
}
}
}
private static void ConcatenateFilesUsingReadAllBytes(string outputFile, params string[] inputFiles)
{
using (var stream = File.OpenWrite(outputFile))
{
foreach (var inputFile in inputFiles)
{
var currentBytes = File.ReadAllBytes(inputFile);
stream.Write(currentBytes, 0, currentBytes.Length);
}
}
}
00:01:22.2753300中的ReadAllBytes方法
00:01:30.3122215中的CopyTo方法
我重复了多次,结果相似。