C# 回滚 Streamreader 1 个字符

4
对于一个C#项目,我正在使用StreamReader,需要回退1个字符(基本上像撤销),并且需要更改,以便在获取下一个字符时,它与回滚时相同。例如:Hello There我们这样做H E L L O [空格] T H E R <-- 我们撤销了R,所以...R <-- 撤销了R R E 那是一个大致的想法。

我认为这是不可能的,因为当你读取一个流时,它会返回并前进,然后就消失了。也许在文件和内存流中可能是可行的,但想想网络流。你读取数据,它正在传入,被处理后就永远消失了,它不会“存储”在某个地方。但是,如果你特别想要这个功能,比如内存流,你可以使用不安全代码进行指针运算,我认为应该可以实现。 - Can Poyrazoğlu
3个回答

2
当你不确定是否需要读取值时,可以使用Peek()而非Read(),这样你就可以在不推进流的情况下检查值。另一种方法(我在我的一些代码中使用)是将读取器(或在我的情况下,一个Stream)封装在一个类中,该类具有内部缓冲区,可以让您推回值。缓冲区始终首先使用,因此很容易将值(甚至是调整后的值)推回流中,而无需倒回它(对于许多流来说这是不起作用的)。

1
一个干净的解决方案是从StreamReader派生一个类并覆盖Read()函数。
对于您的要求,一个简单的private int lastChar就足以实现Pushback()方法。更一般的解决方案将使用Stack<char>来允许无限的pushbacks。
//untested, incomplete
class MyReader : StreamReader
{
    public MyReader(Stream strm)
        : base(strm)
    {
    }

    private int lastChar = -1;
    public override int Read()
    {
        int ch;

        if (lastChar >= 0)
        {
            ch = lastChar;
            lastChar = -1;
        }
        else
        {
            ch = base.Read();  // could be -1 
        }
        return ch;
    }

    public void PushBack(char ch)  // char, don't allow Pushback(-1)
    {
        if (lastChar >= 0) 
          throw new InvalidOperation("PushBack of more than 1 char");

        lastChar = ch;
    }
}

-3

将位置减一:

var bytes = Encoding.ASCII.GetBytes("String");
Stream stream = new MemoryStream(bytes);
Console.WriteLine((char)stream.ReadByte()); //S
Console.WriteLine((char)stream.ReadByte()); //t
stream.Position -= 1;
Console.WriteLine((char)stream.ReadByte()); //t
Console.WriteLine((char)stream.ReadByte()); //r
Console.WriteLine((char)stream.ReadByte()); //i
Console.WriteLine((char)stream.ReadByte()); //n
Console.WriteLine((char)stream.ReadByte()); //g

对于StreamReader,访问其BaseStream属性并设置其Position。 - Ryan Andres
并非所有流都具有CanSeek() == true的属性。 - H H
请注意,Position属性仅受某些流实现的支持,例如NetworkStream 不支持它。使用流的CanSeek属性来确定是否可能。 - Stu Mackellar
2
-1 的原因有三个:a: 字节与字符不同,b: 问题是 StreamReader,c: 不是所有的流都可寻址。 - Marc Gravell
2
@Ryan - 另外,关于“访问其BaseStream”的问题 - 如果你这样做,你需要担心读取器的缓冲区 - 而且,并非所有流都是可寻址的(如果可能的话,最好避免使用寻址)。 - Marc Gravell

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