我尝试读取文件并生成一个新文件,其中没有包含" HEADER"或" TRAILER"。以下是我的代码。当我在text [i] .Remove(i)上放置断点时,它似乎执行该代码但文本变量从不删除该行。任何帮助将不胜感激。
var text = File.ReadAllLines(fileName);
int i = 0;
foreach (string line in text)
{
if (line.Substring(0, 20).Contains("HEADER") || line.Substring(0, 20).Contains("TRAILER"))
{
text[i].Remove(i);
}
else
{
i++;
}
}
string newFN = fileName + "b";
File.WriteAllLines(newFN, text);
答案 0 :(得分:1)
您无法在枚举器中更改可枚举。创建新的可写集合并仅插入与谓词匹配的行,或使用LINQ创建已应用条件的新枚举,然后将其映射到数组或列表或您需要的任何集合。
答案 1 :(得分:1)
ReadAllLines
返回一个字符串数组。您可以使用LINQ从text
var text = File.ReadAllLines(fileName).Select(i => {line.Contains("HEADER")? "": line});
File.WriteAllLines(newFN, text);
答案 2 :(得分:1)
File.WriteAllLines(filename + "b", File.ReadAllLines(filename)
.Select(l => l.Substring(0, 20))
.Where(s => !s.Contains("HEADER") && !s.Contains("TRAILER")));
您可以读取所有行,选择每行的前20个字符,然后使用Where
排除前20个字符包含HEADER或TRAILER的所有行,然后将这些结果行写入文件
答案 3 :(得分:1)
我会使用ReadLines而不是ReadAllLines
,因为它允许您在读取文件的更多行时进行枚举。这样,在开始写出新文件之前,您不必将整个文件读入内存。然后,您可以将代码简化为这一行:
File.WriteAllLines(fileName + "b", File.ReadLines(fileName).Where(line => !line.Contains("HEADER") | !line.Contains("TRAILER")));
这将导致它在写入新文件时遗漏HEADER和TRAILER行。
此外,为了更完整地回答您的问题,String.Remove将从索引中删除所有字符到字符串末尾并返回一个新字符串。 .Net中的字符串是不可变的,因此它不会修改当前字符串,只需返回一个新字符串即可。此外,当您在比较中调用Substring
时,这些方法正在创建新的字符串实例,以便您检查字符串是否包含在该字符串中。最好只在字符串上调用Contains
。
答案 4 :(得分:1)
var lines = File.ReadLines(fileName);
var filtered = lines.Where(line => !line.Contains("HEADER") && !line.Contains("TRAILER")));
File.WriteAllLines(filename + "b", filtered); // or filename.Replace(".txt", "b.txt") ?
.Substring(0, 20)
为新字符串分配内存,对于少于20个字符的行会失败,因此在大多数情况下,只有.Contains
会更快。或者,您可以改为使用.IndexOf
:
line.IndexOf("HEADER", 0, 20, StringComparison.OrdinalIgnoreCase) < 0
我猜测,通过避免一些额外的内存分配,RegEx可能会更快一些:
string text = File.ReadAllText(fileName);
string[] parts = Regex.Split(text, @"\n?\r?.*(HEAD|TRAIL)ER.*\n?\r?");
File.WriteAllLines(filename + "b", parts);