繁体   English   中英

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

[英]C# Search file for a string and get the string's line number

我整天都在这里,我正在努力做到这一点,我搜索得越来越远,虽然有类似的问题,但没有答案。

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

到目前为止我尝试过的我已经尝试了以下代码,我的尝试是读取文件然后接收行号,但它似乎根本不起作用。

            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 ”。

我认为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);

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

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);

你在每一次迭代上编写文件是没有意义的,而做一个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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM