我有1-2 GB大小的文件。我需要在整个文件中找到一些字符串并将其替换为其他字符串。将其写入其他文件不是问题。但我想在同一个文件中替换它。对于小尺寸文件下面的代码工作正常。
var InboxFiles = Directory.GetFiles(@"C:\Users\AAAA\Desktop\Batch Docs");
foreach (var InboxFilePathNM in InboxFiles)
{
StreamReader reader = new StreamReader(InboxFilePathNM);
string content = reader.ReadToEnd();
reader.Close();
content = Regex.Replace(content, @"[^\u0000-\u007F]", "?");
StreamWriter writer = new StreamWriter(InboxFilePathNM.Remove(InboxFilePathNM.Length - 4, 4) + "_NEW.EXT");
writer.Write(content);
writer.Close();
}
无论如何都要在同一个文件中用其他字符串替换字符串。任何人都可以指导。
答案 0 :(得分:5)
这通常不可能,当然不适用于StreamReader / Writer。文本文件是 streams ,每行都有不可预测的长度,只能通过从头开始读取流来找到。 替换线的核心障碍是替换必须与原始线完全相同。如果不是那么超出该行的文本将被破坏。如果替换很短,则原始行的片段存活,或者如果替换很长,则覆盖下一行的一部分。
也许你有这样的保证,然后你需要使用FileStream,这样你才能正确找到行开头的位置。 StreamReader是不合适的,它会提前读取文本编码,因此其底层流的Stream.Position太大。您必须处理字节,首先找到行结束字符(' \ n'),然后使用Encoding类将字节转换为文本,然后查找匹配项。 Seek()回到行的开头来覆盖它。如果文件中包含的行很长,不适合您使用的字节[],则代码非常不愉快,可能是您可以使用的另一种快捷方式。
请记住,编写此类代码通常不会使程序更快。缓慢的部分是读取文件,写入速度非常快。读取速度很慢,因为文件数据需要从磁盘上下来,程序无法继续,直到完成。对于消费级主轴驱动器,通常约为30兆字节/秒。大约一分钟的2 GB文件。写入非常快,内存到内存复制到文件系统缓存中。从懒惰地写入磁盘,通常在程序结束后很久。只有当机器没有足够的RAM并且写入不适合缓存时,您的代码才会更快。
请注意测试效果,在测试程序时,它会非常快速地看。因为您在同一文件上重复运行它。这使得读取速度很快,它们来自文件系统缓存。这在现实生活中并不会发生。由于它正在读取瓶颈,并且您无法跳过阅读要求,因此您实际上并未领先于此类代码。只需确保机器有足够的RAM,8 GB的成本低于100美元。比你花费的少得多:)确保永远不需要等待程序完成。看着草的生长让任何程序员都在寻找更好的方法。当然有一个,一个数据库。
答案 1 :(得分:2)
我认为一个好的选择可能是使用FileStream
。作为FileOPtion,您应该使用SequentialScan
表示从头开始按顺序访问文件 结束系统可以使用它作为优化文件缓存的提示。如果 应用程序移动文件指针以进行随机访问,最佳 缓存可能不会发生;但是,仍然保证正确的操作。 指定此标志可以提高应用程序的性能 使用顺序访问读取大文件。性能提升可以 对于大多数读取大文件的应用程序来说更加引人注目 顺序,但偶尔跳过小范围的字节。
您还可以配置缓冲区大小维度,尝试一些值并更改满足您需求的最快值(例如1024)。
之后,您可以逐行解析文件