我正在尝试每季度清理一些文件。它们有一堆重复的标题,我想一次替换多个字符串值。我可以一次删除一个字符串,但我不知道如何流式传输文件并查看每一行并删除它是字符串1还是字符串2.
每个文件至少有100-300万行,每次将数据转发给我大约每季度一次,我得到10到50个文件...如果他们没有添加这些行,会更容易但这不是一种选择。
很抱歉新手问题,但我不经常使用代码。任何帮助表示赞赏...
static void Main(string[] args)
{
string tempFile = Path.GetTempFileName();
string t1 = "-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
string fName = "C:\\PoC\\test\\test.txt";
using (var sr = new StreamReader(fName))
using (var sw = new StreamWriter(tempFile))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.Contains(t1) == false)
{
sw.WriteLine(line);
}
}
sr.Close();
sw.Close();
}
File.Delete(fName);
File.Move(tempFile, fName);
}
答案 0 :(得分:1)
调用string.Contains()几乎和调用string.Replace()一样昂贵,因为在任何一种情况下都必须扫描整个行以查找子字符串。在Replace()查找匹配的情况下,它创建并返回表示替换结果的新字符串,否则返回原始字符串。变化
if (line.Contains(t1) == false)
sw.WriteLine(line);
到
sw.WriteLine(line.Replace(t1, whatYouWantToReplaceWith));
如果要在一行中替换多个值,可以编写
sw.WriteLine(
line
.Replace(t1, whatYouWantToReplaceWith1)
.Replace(t2, whatYouWantToReplaceWith2)
.Replace(t3, whatYouWantToReplaceWith3)
);
请注意,使用多个.Replace()会导致多次扫描行匹配。虽然这会略微降低性能,但是大部分处理时间可能仍然是文件IO。
如果您知道替换只会发生,例如在第一行中,您可以添加一个计数器来跟踪您所在的行号,并仅将Replace()代码应用于相应的行。
请注意,可能会通过using a BufferedStream对大文件进行一些额外的改进。
<强>更新强>
基于您只想删除该行的声明,我建议您使用@ Eser的答案。
答案 1 :(得分:1)
我想一次替换多个字符串值。
使用Linq可以使您的代码更简单
string[] stringsToRemove = new[] { "str1", "str2", "str2" };
var query = File.ReadLines(fName)
.Where(line => !stringsToRemove.Any(s => line.Contains(s)));
File.WriteAllLines(tempFile, query);
答案 2 :(得分:1)
我知道你正在研究ac#程序,如果目的只是删除与模式相匹配的行,那么我会使用类似Unix Stream editor sed
命令的内容,请参阅sed for Windows stand alone command,或cygwin并且您可以简单地使用该命令删除与模式匹配的所有行以及跟随它的行,您可以编写.bat脚本来复制,重命名,删除匹配多个模式的行。它真的很快。
sed -i '/^---------/d' filepath