C# 如何在文本文件的第一行插入行?
我有一个测试文件,其中包含C# 如何在文本文件的第一行插入行?,c#,C#,我有一个测试文件,其中包含 1,2,3 2,3,4 5,6,7 我想把它插入第一行:A,B,C 因此,我得到: A,B,C 1,2,3 2,3,4 5,6,7 我如何才能做到这一点?这里有一个链接,解释了如何在C#中使用TextReader(StreamReader)和TextWriter(StreamWriter)类 尽管这是C#特有的,但在许多语言中,这种方法可能是相对相同的 (注意:有几种方法可以做到这一点,这只是一个很快浮现在脑海中的想法。) 基本上,您可以将文本文件的内容读入一个
1,2,3
2,3,4
5,6,7
我想把它插入第一行:A,B,C
因此,我得到:
A,B,C
1,2,3
2,3,4
5,6,7
我如何才能做到这一点?这里有一个链接,解释了如何在C#中使用TextReader(StreamReader)和TextWriter(StreamWriter)类 尽管这是C#特有的,但在许多语言中,这种方法可能是相对相同的 (注意:有几种方法可以做到这一点,这只是一个很快浮现在脑海中的想法。)
基本上,您可以将文本文件的内容读入一个字符串,找到该字符串的开头,写入信息(使用回车符或换行符a、B、C),然后将该信息写回文本文件,覆盖原始内容并保存。您不能在文本文件中“插入”任何内容 你必须
- 复制内容
- 在适当的时间提供额外的数据
- 关闭文件
- 删除原始名称并将新名称重命名为旧名称
我认为这个答案更简单、更快:
public static void WriteToFile(string Path, string Text)
{
string content = File.ReadAllText(Path);
content = Text + "\n" + content;
File.WriteAllText(Path, content);
}
那么你可以称之为:
WriteToFile("yourfilepath", "A,B,C");
@杰克:StringBuilder更好更简单
public static void WriteToFile(string path, string text)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("a,b,c");
stringBuilder.Append(File.ReadAllText(path)).AppendLine();
File.WriteAllText(path, stringBuilder.ToString());
}
编辑:
但是StringBuilder有一个缓冲区限制:最大容量2147483647晚到派对
好问题。您可以使用以下代码:
static void WriteABC2(string filename)
{
string tempfile = Path.GetTempFileName();
using (var writer = new FileStream(tempfile, FileMode.Create))
using (var reader = new FileStream(filename, FileMode.Open))
{
var stringBytes = Encoding.UTF8.GetBytes("A,B,C" + Environment.NewLine);
writer.Write(stringBytes, 0, stringBytes.Length);
reader.CopyTo(writer);
}
File.Copy(tempfile, filename, true);
File.Delete(tempfile);
}
此代码基于出色的答案,但我使用FileStream
而不是StreamWriter
和StreamReader
。在处理大文件时,使用FileStream
可以大大提高性能(比我的测试快4倍)。只是想说清楚一点,我做了一些测试,并在下面报告了结果
我是如何做测试的
我创建了7个文件。每个文件包含10^X行,其名称为file.txt
。因此,文件列表如下所示:
| File name | Line count | File size |
|-----------------|------------|-----------|
| file1.txt | 1 | 66 byte |
| file10.txt | 10 | 678 byte |
| file100.txt | 100 | 6,72 KB |
| file1000.txt | 1000 | 68,2 KB |
| file10000.txt | 10000 | 692 KB |
| file100000.txt | 100000 | 6,85 MB |
| file1000000.txt | 1000000 | 69,5 MB |
每个文件的每一行由以下内容组成:
<line index starting from 0> - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
我使用以下代码进行测试并获得函数执行持续时间:
var stopwatch = new Stopwatch();
long abcTotalDuration = 0;
long abc2TotalDuration = 0;
string fileInput = "file1.txt";
string outputFolder = "output";
for (int i = 0; i < 100; i++)
{
string filename1 = Path.Combine(outputFolder, Guid.NewGuid().ToString());
string filename2 = Path.Combine(outputFolder, Guid.NewGuid().ToString());
stopwatch.Restart();
WriteABC(fileInput, filename1);
stopwatch.Stop();
abcTotalDuration += stopwatch.ElapsedMilliseconds;
stopwatch.Restart();
WriteABC2(fileInput, filename2);
stopwatch.Stop();
abc2TotalDuration += stopwatch.ElapsedMilliseconds;
File.Delete(filename1);
File.Delete(filename2);
}
Console.WriteLine("ABC : " + abcTotalDuration.ToString());
Console.WriteLine("ABC2: " + abc2TotalDuration.ToString());
// Just to wake me up :-)
Console.Beep(800, 1000);
Console.ReadKey();
处理文件10.txt
处理文件100.txt
处理文件1000.txt
处理文件10000.txt
处理文件100000.txt
处理文件1000000.txt
从
file10000.txt
中,差异变得非常显著。如果您的文件是10MB或100MB,该怎么办?你能把这些都读入一个字符串(在内存中)吗?这不是很有效。+1-诱惑是相信你可以在文件的开头“插入”一行,而剩下的就完好无损了。它不是那样工作的,所以你指出它是对的。约书亚确实提到了StreamReader和StreamWriter。如果Gold同时使用这两种方法,那么它可以一行一行地完成,这同样不是很有效,但它可以工作而不必担心OutOfMemoryException。答案是:“您可以将文本文件的内容读入字符串”。这只是一个坏主意,除非你确信文件永远不会超过某个大小(取决于你的环境)。@rwwilden:你似乎在鼓吹不可能的事情。你检验过这个理论吗?请参阅对您答案的评论。@rwwilden:事实上,您只能“在末尾插入”,即追加,其他任何内容都会覆盖现有文件的一部分。很抱歉造成混淆,我的答案只覆盖部分文件,根本不插入。太棒了,但我想知道,我们应该是“file.Delete(tempfile)”吗是的,最好是删除文件,为什么还要留下我们不再需要的东西呢?这对较小的文件很好,但对于较大的文件,您可能会遇到内存问题。我们需要指定编码,否则,它会很好地读取文件,但会使用不同的编码写入文件。
0 - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
1 - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
var stopwatch = new Stopwatch();
long abcTotalDuration = 0;
long abc2TotalDuration = 0;
string fileInput = "file1.txt";
string outputFolder = "output";
for (int i = 0; i < 100; i++)
{
string filename1 = Path.Combine(outputFolder, Guid.NewGuid().ToString());
string filename2 = Path.Combine(outputFolder, Guid.NewGuid().ToString());
stopwatch.Restart();
WriteABC(fileInput, filename1);
stopwatch.Stop();
abcTotalDuration += stopwatch.ElapsedMilliseconds;
stopwatch.Restart();
WriteABC2(fileInput, filename2);
stopwatch.Stop();
abc2TotalDuration += stopwatch.ElapsedMilliseconds;
File.Delete(filename1);
File.Delete(filename2);
}
Console.WriteLine("ABC : " + abcTotalDuration.ToString());
Console.WriteLine("ABC2: " + abc2TotalDuration.ToString());
// Just to wake me up :-)
Console.Beep(800, 1000);
Console.ReadKey();
| ABC | ABC2 |
|-----|------|
| 285 | 305 |
| 356 | 352 |
| 435 | 371 |
| 355 | 313 |
| 362 | 372 |
|-----|-----|------|
AVG | 359 | 343 |
|-----|-----|------|
| ABC | ABC2 |
|-----|------|
| 256 | 251 |
| 273 | 323 |
| 355 | 347 |
| 350 | 314 |
| 315 | 286 |
|-----|-----|------|
AVG | 310 | 304 |
|-----|-----|------|
| ABC | ABC2 |
|-----|------|
| 247 | 253 |
| 239 | 246 |
| 357 | 353 |
| 387 | 334 |
| 333 | 329 |
|-----|-----|------|
AVG | 313 | 303 |
|-----|-----|------|
| ABC | ABC2 |
|------|-------|
| 977 | 924 |
| 784 | 738 |
| 818 | 764 |
| 1142 | 1101 |
| 975 | 903 |
|-----|------|-------|
AVG | 939 | 886 |
|-----|------|-------|
| ABC | ABC2 |
|------|-------|
| 1150 | 748 |
| 1147 | 811 |
| 1069 | 654 |
| 1181 | 799 |
| 1234 | 805 |
|-----|------|-------|
AVG | 1156 | 763 |
|-----|------|-------|
| ABC | ABC2 |
|------|-------|
| 5485 | 1769 |
| 5268 | 1528 |
| 5296 | 1555 |
| 5308 | 1529 |
| 5289 | 1553 |
|-----|------|-------|
AVG | 5329 | 1587 |
|-----|------|-------|
| ABC | ABC2 |
|-------|--------|
| 49034 | 12633 |
| 52116 | 12484 |
| 51643 | 12109 |
| 52022 | 12359 |
| 53145 | 12716 |
|-----|-------|--------|
AVG | 51592 | 12460 |
|-----|-------|--------|