2009-05-19 73 views

回答

8

新的答案

(请参阅下面的废弃,另外添购原有答案的解释。)

static void CopyFiles(string dest, params string[] sources) 
{ 
    using (TextWriter writer = File.CreateText(dest)) 
    { 
     // Somewhat arbitrary limit, but it won't go on the large object heap 
     char[] buffer = new char[16 * 1024]; 
     foreach (string source in sources) 
     { 
      using (TextReader reader = File.OpenText(source)) 
      { 
       int charsRead; 
       while ((charsRead = reader.Read(buffer, 0, buffer.Length)) > 0) 
       { 
        writer.Write(buffer, 0, charsRead); 
       } 
      } 
     } 
    } 
} 

这个新的答案非常喜欢马丁的做法,除了:

  • 它读成较小的缓冲区16K将是在几乎所有情况下接受的,而且在大对象堆不会结束(不得到压实)
  • 它读取文本数据,而不是二进制数据,原因有二:
    • 的代码可以容易地被修改以从一种编码转换为另一种
    • 如果每个输入文件包含一个字节顺序标记,将由读取器被跳过,而不是用散射字节顺序标记结束了通过输入文件的输入文件边界

原来的答复

马丁别人接受指出了下面的答案的一个问题 - 如果第一个文件,而无需换行结束,它仍然会造成在输出文件中换行。此外,即使它们以前只是“\ r”或“\ n”,它也会将换行符转换为“\ r \ n”。最后,它毫无意义地冒着为长线使用大量数据的风险。

喜欢的东西:

static void CopyFiles(string dest, params string[] sources) 
{ 
    using (TextWriter writer = File.CreateText(dest)) 
    { 
     foreach (string source in sources) 
     { 
      using (TextReader reader = File.OpenText(source)) 
      { 
       string line; 
       while ((line = reader.ReadLine()) != null) 
       { 
        writer.WriteLine(line); 
       } 
      } 
     } 
    } 
} 

注意,这逐行地读取,以避免过分解读内存在的时间。如果你(在时间还是一个)很高兴能完整地阅读每一个文件到内存中,你可以更简单:

static void CopyFiles(string dest, params string[] sources) 
{ 
    using (TextWriter writer = File.CreateText(dest)) 
    { 
     foreach (string source in sources) 
     { 
      string text = File.ReadAllText(source); 
      writer.Write(text); 
     } 
    } 
} 
+0

Skeet再次击败我! – jrcs3 2009-05-19 20:44:17

+0

他只是看看他的键盘,它开始用光速输入答案。:) – 2009-05-19 20:45:22

2

编辑

由于乔恩斯基特指出,文本文件通常应被处理的方式不同于二进制文件 。

我刚刚离开这个答案,因为它可能是更好的性能,如果你有非常大的文件,而不是通过编码的问题(例如,具有在输出文件中不同的编码或多个Byte Order Marks不同的输入文件)concernded:

public void CopyFiles(string destPath, string[] sourcePaths) { 
    byte[] buffer = new byte[10 * 1024 * 1024]; // Just allocate a buffer as big as you can afford 
    using (var destStream= = new FileStream(destPath, FileMode.Create) { 
    foreach (var sourcePath in sourcePaths) { 
     int read; 
     using (var sourceStream = FileStream.Create(sourcePath, FileMode.Open) { 
     while ((read = sourceStream.Read(buffer, 0, 10*1024*1024)) != 0) 
      destStream.Write(buffer, 0, read); 
     } 
    } 
    } 
} 
相关问题