3

我编写了这个小程序,它从 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,例如 a 的结尾BaseStream。我预计,显然是错误的,当我打电话给checkBaseStream.Position时会保持不变?EndOfStream

谢谢。

4

3 回答 3

4

找出 aStream是否在其末尾的唯一确定方法是实际从中读取一些内容并检查返回值是否为 0。(StreamReader还有另一种方法 - 检查其内部缓冲区,但您正确地不要让它这样做打电话DiscardBufferedData。)

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

看来您实际上并不需要使用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;
    }
}

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

于 2011-09-29T14:05:56.450 回答
2

基本流的Position属性是指缓冲区中最后一个读取字节的位置,而不是 StreamReader 光标的实际位置。

于 2011-09-29T12:49:13.203 回答
1

你是对的,我也可以重现你的问题,无论如何根据(MSDN:从文件中读取文本),使用 StreamReader 读取文本文件的正确方法如下,而不是你的(这也总是关闭并处理流通过使用 using 块):

try
{
    // Create an instance of StreamReader to read from a file.
    // The using statement also closes the StreamReader.
    using (StreamReader sr = new StreamReader("TestFile.txt"))
    {
        String line;
        // Read and display lines from the file until the end of
        // the file is reached.
        while ((line = sr.ReadLine()) != null)
        {
            Console.WriteLine(line);
        }
    }
}
catch (Exception e)
{
    // Let the user know what went wrong.
    Console.WriteLine("The file could not be read:");
    Console.WriteLine(e.Message);
}
于 2011-09-29T12:11:20.477 回答