C#搜索文件中的字符串并获取字符串的行号

时间:2015-09-03 16:48:08

标签: c# io lines

我整天都在这里,而且我正努力做到这一点,我已经进行了广泛的搜索,尽管有类似的问题,但没有答案。

我想做的事情: 我试图在文件中搜索多个字符串并接收行号,以便当用户希望更改我的应用程序中的所述字符串时,我的应用程序知道要用其字符串替换哪些行。

到目前为止我尝试了什么: 我尝试过下面的代码,我的尝试是阅读文件,然后收到行号,但它似乎并没有起作用。

            var lines = File.ReadAllLines(filepath);
            foreach (var match in lines // File.ReadLines(filePath)
                            .Select((text, index) => new { text, lineNumber = index + 1 })
                            .Where(x => x.text.Contains("motd=")))
            {
                lines[match.lineNumber] = "motd=" + textBox1.Text;
                File.WriteAllLines(filepath, lines);
            }
        }

我希望上面的代码能找到字符串" motd ="在文件中,获取行号并尝试用用户输入的内容重新写入。

但是,我收到此错误:" Index was outside the bounds of the array"。

3 个答案:

答案 0 :(得分:5)

我认为for循环在这里更有意义

var lines = File.ReadAllLines(filepath);
for (int i = 0; i < lines.Length; i++)
{
    if(lines[i].Contains("motd="))
    {
        lines[i] = "motd=" + textBox1.Text;
    }
}

File.WriteAllLines(filepath, lines);

你的代码的一些问题是你在循环中写出文件并且你将索引增加1然后指向数组中的错误行并导致你获得的异常如果最后一行包含您要搜索的文本。

应该注意的是,如果你正在使用一个非常大的文件,这可能是一个内存耗尽。在这种情况下,我会一次读取一行并将它们写入临时文件,然后删除原始文件并在结尾重命名temp。

var tempFile = Path.GetTempFileName();
using (var file = File.OpenWrite(tempFile))
using (var writer = new StreamWriter(file))
{
    foreach (var line in File.ReadLines(filepath))
    {
        if (line.Contains("motd="))
        {
            writer.WriteLine("motd=" + textBox1.Text);
        }
        else
        {
            writer.WriteLine(line);
        }
    }
}

File.Delete(filepath);
File.Move(tempFile, filepath);

答案 1 :(得分:2)

这会更快,使用更少的内存,并使用非常大的文件,但你需要写入一个新文件:

File.WriteAllLines(filepath2,
  File
    .ReadLines(filepath)
    .Select(x=>x.Contains("motd=")?"motd="+TextBox1.Text:x));

它使用ReadLines,它尽可能读取每一行而不是读取整个文件并在一步中将其分成行。因此,它会在文件系统读取,处理行,然后写入结果时快速处理它。

完全替换将如下所示:

var filepath2= Path.GetTempFileName();
File.WriteAllLines(filepath2,
  File
    .ReadLines(filepath)
    .Select(x=>x.Contains("motd=")?"motd="+TextBox1.Text:x));
File.Delete(filepath);
File.Move(filepath2, filepath);

要做多个值:

var filepath2= Path.GetTempFileName();
File.WriteAllLines(filepath2,
  File
    .ReadLines(filepath)
    .Select(x=> {
      if (x.Contains("motd=")) return "motd="+TextBox1.Text;
      if (x.Contains("author=")) return "author="+TextBox2.Text;
      return x;
    }));
File.Delete(filepath);
File.Move(filepath2, filepath);

或将替换逻辑移动到它自己的功能:

string ReplaceTokens(string src)
{
  if (src.Contains("motd=")) return "motd="+TextBox1.Text;
  if (src.Contains("author=")) return "author="+TextBox2.Text;
  return src;
}
var filepath2= Path.GetTempFileName();
File.WriteAllLines(filepath2,
  File
    .ReadLines(filepath)
    .Select(ReplaceTokens));
File.Delete(filepath);
File.Move(filepath2, filepath);

答案 2 :(得分:1)

你在每一次迭代都没有意义的情况下编写文件,并且做一个select / where / index事情只是很奇怪。

由于您正在执行Where,您必须遍历每一行,那么为什么不省去麻烦并只是明确地迭代所有内容?

var lines = File.ReadAllLines(filepath);
for(int i = 0; i < lines.Length; i++)
{
    if(lines[i].Contains("motd="))
    {
        lines[i] = "motd=" + textBox1.Text;
    }
}

File.WriteAllLines(filepath, lines);