【问题标题】:After StreamWriter.WriteLine(), FileStream.SetLength(0) does not empty the fileStreamWriter.WriteLine()之后,FileStream.SetLength(0)不清空文件
【发布时间】:2017-05-11 16:15:20
【问题描述】:

我发现 FileStream.SetLength(0) 有一个奇怪的问题。当首先向流写入内容然后调用 SetLength(0) 时,之前写入的内容仍会写入文件:

var fileName = "test.txt";
using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8000, FileOptions.None)) 
{
    using (var streamWriter = new StreamWriter(fileStream, Encoding.Default, bufferSize: 8000, leaveOpen: true)) 
    {
        streamWriter.WriteLine("123");
        fileStream.SetLength(0);
        streamWriter.WriteLine("abc");
    }
}
  var fileContent = File.ReadAllText(fileName);

文件内容变为“123\r\nabc\r\n”

很明显,123并没有被删除,即使它是在调用SetLength(0)之前写的。

使用 Seek() 或将 Position 设置为 0 没有帮助。

在我的应用程序中,我正在写入一个保持打开状态的文件。有时,我可能需要完全清空文件并写入不同的内容。出于性能原因,我不想关闭 streamWriter。

所有喜欢将错误的问题标记为重复问题的人注意

我在 Stackoverflow 上遇到了一个非常令人沮丧的经历,即一个问题被错误地标记为重复。我花了一天时间写这个问题,他立刻断定它是重复的,即使它不是。这通常发生在那个人没有真正理解问题并且不想找到正确答案的时候。他只是觉得以前在 SO 上解决了类似的问题。但细节很重要。是的,有一些关于使用 SetLength(0) 截断文件的问题,但它们在一个关键点上有所不同:在这些示例中, SetLength(0) 前面没有 Write()。但这是必不可少的,没有它也没有问题。

在通过将问题标记为重复来阻止其他人回答时,请务必小心谨慎。

【问题讨论】:

  • StreamWriter 不知道你在搞乱它的底层流。它本身有一个缓冲区,你必须 Flush() 它。
  • 真正清除的唯一方法是关闭并作为新流再次打开。
  • @jdweng:我使用 Flush() 的解决方案似乎有效,尽管我可能没有意识到它会产生问题。你能描述一下那可能是什么吗?
  • 在向流中写入大量数据后尝试flush()。

标签: c# filestream file-handling streamwriter


【解决方案1】:

在检查 FileStream.SetLength() on referencesource.microsoft.com 时,我注意到了这段看起来很有趣的代码:

        // Handle buffering updates.
        if (_writePos > 0) {
            FlushWrite(false);
        }

它在 SetLength() 中检查内部 FileStream 缓冲区是否还有一些写入内容,并首先将其写入文件,然后再执行 SetLength() 的其余部分。

一个非常奇怪的行为。我可以通过先使用 Flush() 在调用 SetLength() 之前清空内部缓冲区来解决这个问题:

  var fileName = "test.txt";
  using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8000, FileOptions.None)) {
    using (var streamWriter = new StreamWriter(fileStream, Encoding.Default, bufferSize: 8000, leaveOpen: true)) {
      streamWriter.WriteLine("123");
      streamWriter.Flush();
      fileStream.SetLength(0);
      streamWriter.WriteLine("abc");
    }
  }
  var fileContent = File.ReadAllText(fileName);

文件内容现在是:“abc\r\n”

我很想知道是否还有其他人认为这是 FileStream 中的错误?

【讨论】:

    猜你喜欢
    • 2014-02-26
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 1970-01-01
    相关资源
    最近更新 更多