【问题标题】:Stream Seek function not reacting as expectedStream Seek 功能未按预期反应
【发布时间】:2017-05-09 14:30:20
【问题描述】:

目标是能够关闭流并返回到相同的位置(作为“书签”)。

编辑:两个用户建议我必须使用streamReader.DiscardBufferedData(),并且至少使Test1Test2 以相同的方式反应。我删除了Test2(信息:它与Test1 完全相同,但关闭并重新打开流),并“修复”Test1

Test1 仍然失败:

public static void Test1(string filePath)
{
    var line1 = default(string);
    var line2 = default(string);
    var line3 = default(string);

    using (StreamReader streamReader = File.OpenText(filePath))
    {
        // read 2 consecutive lines:
        line1 = streamReader.ReadLine();
        var line2StreamPosition = streamReader.BaseStream.Position; // save position at the begining of line2:
        line2 = streamReader.ReadLine();

        // go back to the position of line2 and try to re-read it:
        streamReader.DiscardBufferedData();
        streamReader.BaseStream.Seek(line2StreamPosition, SeekOrigin.Begin);
        line3 = streamReader.ReadLine();

        if (line2 == line3)
        {
            // it doesn't reach this point
        }
        else
        {
            // it fails ...
            // it starts reading `line3` at an incorrect position
        }

    }
}

还有:var canSeek = streamReader.BaseStream.CanSeek; // true

【问题讨论】:

  • 我认为这和here是同一个问题。设置位置是不够的。您还需要告诉流丢弃其缓冲区。
  • @Amy 谢谢,这解决了Test1 的问题。现在两个测试的反应方式相同(但它们都失败了)。
  • 你所做的不能可靠地工作。阅读MSDN documentationStreamReader(Stream stream) 构造函数,尤其是备注部分。你注意到关于内部缓冲区的一点吗?简而言之:当您从 StreamReader 读取一行时,读取器不仅从底层流中读取行的字节,而且读取尽可能多的字节来填充内部缓冲区。因此,line2StreamPosition 不一定是流中第二个字符串/行的位置。
  • 您可以创建自己的 StreamReader 类(如果可能),而不是操作底层流,您可以扩展它以允许将字符串/行放回阅读器...

标签: c# filestream


【解决方案1】:

您可以使用相应的编码计算书签位置,但这里的问题是没有简单的方法来确定构成换行符的字符是什么;它不一定是Environment.NewLine

如果您事先确实知道在您的环境中哪些字符构成了换行符,您可以执行以下操作:

var line2StreamPosition = streamReader.CurrentEncoding
                                      .GetByteCount(
                                           string.Concat(line1, myNewLine)
                                                 .ToArray());

【讨论】:

  • 你昨天问的属性为空(而不是空)的问题是怎么回事?你明白了吗?
  • @stt106 VS 在调试时加载本地变量的方式肯定存在错误,但由于其他原因断言失败。这不是因为我错误地认为的空引用异常。这改变了问题的整体设置,所以我决定删除它。我可以忍受调试错误,真正令人困惑的是由于该错误导致断言失败,但事实并非如此。
猜你喜欢
  • 2013-08-29
  • 1970-01-01
  • 2020-04-28
  • 2021-08-27
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 2020-10-02
  • 2012-10-07
相关资源
最近更新 更多