How to read multiple text files and save them to one text file?
2 answers
New answer
(See the explanations for the original answer to spam below.)
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);
}
}
}
}
}
This new answer is very similar to Martin's approach, except:
- It reads into a smaller buffer; 16K will be acceptable in almost all situations and will not be on a large object heap (which is not compacted).
- It reads text data instead of binary data for two reasons:
- The code can be easily modified to convert from one encoding to another
- If each input file contains a byte-order character that will be skipped by the reader instead of ending with byte-order characters scattered throughout the output file at the input file boundaries.
Original Answer
Martin Stetner pointed out the problem in the answer below - if the first file ends without a newline, it will still create a newline in the output file. In addition, it will translate newlines to "\ r \ n" even if they were previously "\ r" or "\ n". Finally, it runs the risk of unnecessarily using large amounts of data for long lines.Sort of:
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);
}
}
}
}
}
Note that this is read line by line to avoid reading too much into memory at a time. You could make it easier if you happily read each file completely into memory (still one at a time):
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);
}
}
}
+8
a source to share
Edit
As Jon Skeet pointed out, text files are usually handled differently than binaries.
I just leave this answer as it might be more efficient if you have really large files and are not associated with encoding issues (eg different input files with different encodings, or multiple "Byte order values" in the output file):
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);
}
}
}
}
+2
a source to share