如何在不重新打开文件的情况下从文本文件中读取并写入/追加内容?

3
我该如何打开一个FileStream,读取文件内容,然后在不重新打开文件的情况下写入(追加)到文件中?
在这种情况下,StreamReader/StreamWriter存在一个问题,即它们假设拥有底层流。由于目标是.NET 4,因此"leaveOpen"构造函数重载无法使用。(我不介意使用StreamReader/StreamWriter,但它们提供了ReadLine和WriteLine操作。)
总之,与问题相关的有问题的代码示例以及应用程序将如何访问和管理FileStream的生命周期(只需打开一次):
var fs = File.Open(..);
using (var reader = new StreamReader(fs)) {
   // Do all reading here, then ditch the reader
}  // .. but StreamReader will Close the FileStream

SeekToEnd(fs);

using (var writer = new StreamWriter(fs)) {
   // Do all writing here, then ditch the writer
   // .. ideal, but FileStream already Closed
}

// Finally, somewhere else:
fs.Close();

我找到的“相关”的MSDN文章总是将其分为两个步骤:这个问题是关于在打开文件两次的情况下以行为单位执行文本的读取-写入操作。

文件被打开为

File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite)

底层流始终可随意定位和写入。


为什么在打开写入器之前必须关闭读取器?为什么不能同时打开它们两个? - gunr2171
"长时间运行的应用程序"。第一阶段是重放日志,第二阶段是追加到同一个日志中...虽然我可以无限期地保留Reader,使其永远不关闭,但我真的想找到一种更好的方法。 - user2864740
我认为流读取器最重要的问题是实际的流,我不认为同时保持它们会有什么危害。在你的情况下,解决这个问题的另一种方法就是实现一个新的流读取器和写入器,不要释放文件流。 - konkked
这不是关于“使用资源”(毕竟只有一个FileStream,读取器使用的整个缓冲区微不足道) - 而是关于“摇头”,因为使用字段仅用于维护读取器生命周期(必须保持GC-alive),并省略在读取周围使用using(这是一个本地操作,写入将发生多次,直到父项被处理)。 - user2864740
1
@user2864740 我理解你想要这样做(因为这样更有意义),但你要么需要自己实现它,要么只能保持变量开放,或者升级到允许使用你提到的标志来保持文件流打开的 .NET 版本。 - konkked
1个回答

5

您可以将流的位置设置为流的末尾,并从那里开始写入。

 fs.Position = fs.Length;
 //then do the write operations you need to do

即使您正在使用流编写器或读取器,也应该能够修改读取器/编写器所使用的FileStream,从而允许您先读取然后写入。
using(var fs = File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite)
{
    using(var reader = new TextReader(fs))
    using(var writer = new TextWriter(fs))
    {
        //read

        fs.Position = fs.Length;

        //write
    }
}

FileStream没有像StreamReader/StreamWriter那样提供类似WriteLine和ReadLine的文本相关操作方法,而且当StreamReader/StreamWriter被Dispose时,它将(默认情况下)自动Dispose底层流。由于我受限于.NET 4,因此我无法使用“leaveOpen”构造函数重载 - user2864740
@user2864740,更新了答案,即使流已被读取器消耗,您仍应该能够修改流。如果是这种情况,请等到结束时处理两个流对象。 - konkked
虽然通过在读取器被处理之后不进行写入(并且Dispose调用是幂等的)的影响,该更新“可以工作”,但它回避了问题。我不想保留读取器“只是为了不关闭源”(它也必须保持GC-alive)。在此应用程序中,读取在开始时仅执行一次,并在一段时间内进行写入,直到应用程序关闭(将其视为日志)。 - user2864740
@user2864740:你是否担心保持TextReader未释放会导致某种性能问题?我怀疑保持TextReader打开的内存成本非常微不足道,因为你想要底层流保持打开状态。 - StriplingWarrior
@StriplingWarrior 不,我不担心“性能” - 我遵循97/3的原则。我还遵循三(或六)种美德。请查看我在主要问题中的评论。 - user2864740
虽然我不喜欢“在写作过程中无限期地让读者开放”,但这种方法确实有效。 - user2864740

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接