【问题标题】:Delete the last line of a StreamWriter?删除 StreamWriter 的最后一行?
【发布时间】:2012-01-19 05:57:37
【问题描述】:

我知道当我们使用 StreamWriter 时,顾名思义,就是在其中写入,但事实是在某些时候我有义务删除我的 StreamWriter 的最后一行...

我发现以下代码(在 SO 上)运行良好:

var lines = System.IO.File.ReadAllLines(pluginQmlFileName);
System.IO.File.WriteAllLines(pluginQmlFileName, lines.Take(lines.Length - 1).ToArray());

但问题是我不能在我的 :

中使用它
using (StreamWriter sw = new StreamWriter(pluginQmlFileName, true))
{
    [...]
}

部分。

有没有办法删除using {} 部分的最后一行,还是我必须保留我的实际代码?

【问题讨论】:

  • 你写的怎么样?如果您有某种循环,请不要在最后一次迭代中编写。
  • 是的,有一个循环,但事实是,当我写最后一行时,我不知道以后要不要删除它:/解释太长了,但我只能检查在下一个循环中,我必须将其删除... :(
  • 那么为什么不使用List<string> 来存储你想写的行,然后在“下一个循环”之后才使用File.WriteAllLines 来写这些行呢?从 List 中删除最后一行是微不足道的。 :)
  • 好吧,我没有正确地解释自己:(我在一个循环中写,但循环在一个函数中,当我再次进入函数时我有时会删除最后一行!(这就是我打开 StreamWriter 的原因使用“true”参数),事实是我只能在 StreamWriter 已经打开时进行测试:/
  • 嗯...这是一个可怕的想法:保留最后一行,而不是写它,将它(使用out 或其他)返回给调用者。调用者可以继续将它传递回您的函数,您的函数可以决定是否应该编写它。但老实说,这听起来像是您将业务逻辑(“我应该写吗?”)混合到常规代码(“我该如何写?”)中。试着把这些东西分开。也许在写函数内部循环不是最好的选择?

标签: c# streamwriter


【解决方案1】:

这就是我解决问题的方法:

StreamWriter myFile = new StreamWriter(fileName, false);
int countLines = 0;
foreach (var line in lines)
{
    countLines++;
    if (countLines == lines.Count)
    {
        //Write doesn't insert "/r/n" on the end of line
        myFile.Write(line.ToString());
    }
    else
    {
        //WriteLine insert "/r/n" on the end of a line
        myFile.WriteLine(line.ToString());
    }
}

【讨论】:

    【解决方案2】:

    这似乎也适用于我:

    //如果有的话,你必须尝试关闭该文件的所有打开的流 //如果你在using (StreamWriter sw = .... ) {....}中使用它 //尝试 => sw.close(); //然后

    FileStream fs = new FileStream(filePath , FileMode.Open, FileAccess.ReadWrite);
    fs.SetLength(fs.Length - 1);
    fs.Close();
    

    【讨论】:

      【解决方案3】:

      不,您不能从 StreamWriter 打开的流中删除任何数据。 StreamWriter 旨在写入文件,因此您不能明确删除任何内容。

      所以必须使用其他类来读取文件内容,然后由于 StreamWriter class 继承自 TextWriter class 你应该可以使用 WriteLine(string) 方法,但这没有意义,因为你已经有一个很好的工作代码。

      // read all lines
      // ...
      var allExceptLast = lines.Take(lines.Length - 1);
      foreach(var line in allExceptLast)
      {
         writer.WriteLine(line);
      }
      

      【讨论】:

      • 是的,但即使使用 TextWriter 也没有“RemoveLine”方法。文字一旦写入,就无法撤消。
      【解决方案4】:

      您可以在全部阅读后删除最后一行:

      var lines = System.IO.File.ReadLines(pluginQmlFileName);
      
      // will need changing to remove from the array if using ReadAllLines instead of ReadLines
      lines = lines.RemoveAt(lines.Count - 1);
      

      【讨论】:

      • 对我的 StreamWriter 问题没有帮助,但这是一个不错的提示!
      • 这取决于你在读写之间做什么。如果您正在阅读然后立即写作,并且知道您想要删除最后一行,那么这样做是值得的。虽然如果不是并且您最终存储了这些行,那么您可以在通过 StreamWriter 写入文件之前删除最后一行。否则可能值得看看 TextWriter。
      【解决方案5】:

      嗯,在上面的代码中,lines 实际上是一个字符串数组,因为ReadAllLines 返回一个字符串数组。

      与其考虑“删除最后一行”,我更愿意考虑“不写最后一行”,所以你可以做什么:

      string[] lines = ...; // Note that I'm using an array here!
      
      using (...)
      {
          for (int i = 0; i < lines.Length; i++)
          {
              if (i < lines.Length-1 || !condition)
                  sw.WriteLine(lines[i]);
          }
      }
      

      这会将所有行写入倒数第二行。仅当条件为假时才写入最后一行。

      【讨论】:

      • 在我的代码中使用它会非常困难:(对我的问题的评论应该解释为什么!
      【解决方案6】:

      我不认为 StreamWriter 允许您这样做,但也许您可以制作自己的流包装器来实现此行为?也就是说,它将最后一行保留在内存中,只有在另一行进入时才将其写入。

      【讨论】:

      • 是的,我就是这样做的。但前提是我不得不写入 SteamWriter。一开始不写似乎更简单,不是吗?
      • 这是我的代码中的一个“重”解决方案...... :(关于不写它,请参阅我对我的问题的评论 (@scraimer)
      • 嗯,是的,这有点重。您为什么不喜欢将所有行存储在 List 中,然后在完成循环后将它们全部写出的想法?
      猜你喜欢
      • 1970-01-01
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-29
      • 1970-01-01
      相关资源
      最近更新 更多