我写了这个小程序,它从Random.txt中读取第5个字符
在random.txt中,我有一行文本:ABCDEFGHIJKLMNOPRST。我得到了预期的结果:


A的位置是0
F的位置是5
K的位置是10
P的位置是15


这是代码:

static void Main(string[] args)
{
    StreamReader fp;
    int n;
    fp = new StreamReader("d:\\RANDOM.txt");
    long previousBSposition = fp.BaseStream.Position;
    //In this point BaseStream.Position is 0, as expected
    n = 0;

    while (!fp.EndOfStream)
    {
        //After !fp.EndOfStream were executed, BaseStream.Position is changed to 19,
        //so I have to reset it to a previous position :S
        fp.BaseStream.Seek(previousBSposition, SeekOrigin.Begin);
        Console.WriteLine("Position of " + Convert.ToChar(fp.Read()) + " is " + fp.BaseStream.Position);
        n = n + 5;
        fp.DiscardBufferedData();
        fp.BaseStream.Seek(n, SeekOrigin.Begin);
        previousBSposition = fp.BaseStream.Position;
    }
}


我的问题是,为什么在while (!fp.EndOfStream) BaseStream.Position行更改为19之后,例如BaseStream的结尾。我期望,显然错误的是,当我调用BaseStream.Position检查时EndOfStream会保持不变吗?

谢谢。

最佳答案

找出Stream是否在其末尾的唯一方法是从其中实际读取内容并检查返回值是否为0。(StreamReader还有另一种方法–检查其内部缓冲区,但是您正确地没有不要通过调用DiscardBufferedData来做到这一点。)

因此,EndOfStream必须从基本流中读取至少一个字节。而且由于逐字节读取效率低下,因此读取更多。这就是为什么EndOfStream调用将位置更改为末尾的原因(对于较大的文件,它不会是文件的末尾)。

看来您实际上并不需要使用StreamReader,因此您应该直接使用Stream(特别是FileStream):

using (Stream fp = new FileStream(@"d:\RANDOM.txt", FileMode.Open))
{
    int n = 0;

    while (true)
    {
        int read = fp.ReadByte();
        if (read == -1)
            break;

        char c = (char)read;
        Console.WriteLine("Position of {0}  is {1}.", c, fp.Position);
        n += 5;
        fp.Position = n;
    }
}


(在这种情况下,我不确定设置超出文件末尾的位置会做什么,您可能需要为此添加一个检查。)

10-06 09:27