【问题标题】:How do I delete all lines in text file below certain text?如何删除文本文件中某些文本下方的所有行?
【发布时间】:2019-10-18 05:15:11
【问题描述】:

我有一个代码,它遍历整个文本文件以搜索特定文本“[names]”,并“尝试”删除文本下方的所有行。我尝试了 File.WriteAllText(INILoc, string.Empty);,但这只会删除整个文本文件中的所有内容。我怎样才能做到只删除“[names]”下面的所有行?

我已经像这样设置了迭代:

string[] lines = File.ReadAllLines(INILoc);
bool containsSearchResul = false;
foreach (string line in lines)
    {
         if (containsSearchResul)
           {
                File.WriteAllText(INILoc, string.Empty);

           }
         if (line.Contains("[names]"))
           {
                containsSearchResul = true;
           }
    }

【问题讨论】:

  • 欢迎来到 StackOverflow!熟悉 docs.microsoft.com 网站可能会有所帮助。 WriteAllText 方法的描述如下: 创建一个新文件,将内容写入文件,然后关闭文件。如果目标文件已经存在,则会被覆盖。 正如@Prasad 在他的回答中提到的,您传入的是 string.Empty,因此您的输出是一个空文件。 File 类上没有内置方法来执行此操作,因此您必须像 Prasad 所做的那样“自行开发”。

标签: c# loops iteration


【解决方案1】:

您需要将"[names]"文本之前的行存储到字符串变量中,当条件(line.Contains("[names]"))满足时,只需中断循环并将字符串值写入同一个文件。

类似的,

string[] lines = File.ReadAllLines(INILoc); //Considering INILoc is a string variable which contains file path.
StringBuilder newText = new StringBuilder();
bool containsSearchResul = false;

foreach (string line in lines)
    {
       newText.Append(line);
       newText.Append(Environment.NewLine); //This will add \n after each line so all lines will be well formatted

       //Adding line into newText before if condition check will add "name" into file
       if (line.Contains("[names]"))
              break;

    }

File.WriteAllText(INILoc, newText.ToString());
                        //^^^^^^^ due to string.Empty it was storing empty string into file.

注意:如果你使用StringBuilder类,那么不要错过在你的程序中添加Using System.Text

【讨论】:

  • 谢谢!但是现在出现了一个新问题,它最终也删除了[names],现在文本文件的所有内容都粘贴在一行中。
  • 我更新了我的答案以涵盖您在评论中提到的两种情况
  • @ChayimFriedman,我同意你的编辑建议,只是我添加了单独的代码行来解释Environment.NewLine背后的原因
  • @PrasadTelkikar 另外,出于性能考虑,最好使用StringBuilder 而不是string
【解决方案2】:

使用StreamReader,因为它会为您提供最佳性能,因为您不需要读取整个文件。将“输入文件路径”替换为您的文件路径,结果将存储在您为“输出文件路径”提供的路径中。

using (var sr = new StreamReader("PATH TO INPUT FILE"))
{
    using (var sw = new StreamWriter("PATH TO OUTPUT FILE"))
    {
        var line = sr.ReadLine();

        while (line != null)
        {
            sw.WriteLine(line);

            if (line.Contains("[names]"))
            {
                sw.Close();
                sr.Close();
            }
            else
            {                            
                line = sr.ReadLine();
            }                        
        }
    }
}

如果需要写入同一个文件:

var sb = new StringBuilder();

using (var sr = new StreamReader("PATH TO INPUT FILE"))
{
    var line = sr.ReadLine();

    while (line != null)
    {
        sb.AppendLine(line);

        if (line.Contains("[names]"))
        {
            sr.Close();
        }
        else
        {
            line = sr.ReadLine();
        }
    }
}

File.WriteAllText("PATH TO INPUT FILE", sb.ToString());

【讨论】:

  • 如果输出和输入文件相同怎么办?那么它给了我一个错误。
  • @ManiacKnight 当然它会给你一个错误,你试图两次流式传输同一个文件。我提供了一个解决方案,让您可以写入同一个文件,同时保持使用流的性能。
【解决方案3】:

根据请求的代码,我已将修改放在一起。

    string[] lines = File.ReadAllLines(INILoc);
    //create a list to hold the lines
    List<string> output = new List<string>();
    //loop through each line
    foreach (string line in lines)
    {
        //add current line to  ouput.
        output.Add(line);
        //check to see if our line includes the searched text;
        if (line.Contains("[names]"))
        {
            //output to the file and then exit loop causing all lines below this 
            //one to be skipped
            File.WriteAllText(INILoc, output.ToArray());
            break;
        }
    }

【讨论】:

    【解决方案4】:

    您的代码的问题在于它删除了[names]之前的所有行,而不是之后(更准确地说,只写该文本之后的行)。此外,任何时候您重写所有文件内容,因此删除所有先前写入的行。它的工作原理如下:

    string[] lines = File.ReadAllLines(INILoc);
    using (StreamWriter writer = new StreamWriter(INILoc)) // https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-write-text-to-a-file
    {
                bool containsSearchResul = false;
                foreach (string line in lines)
                {
    
                    if (!containsSearchResul)
                    {
                        writer.Write(INILoc, string.Empty);
    
                    }
    
                    if (line.Contains("[names]"))
                    {
                        containsSearchResul = true;
                    }
                }
    }
    

    您有另一个更好的选择来使用break

    string[] lines = File.ReadAllLines(INILoc);
    using (StreamWriter writer = new StreamWriter(INILoc)) // https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-write-text-to-a-file
    {
                foreach (string line in lines)
                {
                    if (line.Contains("[names]"))
                    {
                        break;
                    }
    
                    writer.WriteLine(INILoc, string.Empty);
                }
    }
    

    但是您可以通过使用 LINQ 以更喜欢、更易读的方式执行此操作:

    using System.Linq;
    
    // ...
    
    string[] lines = File.ReadAllLines(INILoc);
    string[] linesTillNames = lines
                              .Take( // Take just N items from the array
                                  Array.IndexOf(lines, "[names]") // Until the index of [names]
                              )
                              .ToArray();
    File.WriteAllLines(INILoc, linesTillNames);
    

    【讨论】:

      【解决方案5】:

      你也可以这样使用:WriteAllLines(string path, IEnumerable&lt;string&gt; contents)

      string[] lines = File.ReadAllLines(INILoc);
      List<string> linesToWrite = new List<string>();
      
      foreach(string line in lines)
      {
          linesToWrite.Add(line);
          if (line.Contains("[names]")) break;
      }
      
      File.WriteAllLines(INILoc, linesToWrite);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        • 2013-11-04
        • 2014-04-19
        相关资源
        最近更新 更多