通常StreamReader是不需要指针的,因为只要一行一行读取,或者一次性全部读取就可以搞定。但也不排除碰到读取一行或者多行后,需要返回从第一行重新读取的时候,这就需要将指针返回到流的起始位置。
因为StreamReader是没有操作指针的函数的,所以我想到了他的上一层父类Stream来操作。但是指针是返回到起始位置了,读取的结果却不尽如人意。研究了一下发现,虽然是依靠Stream类中的指针,但在二进制中是没法判断一行的结束的,所以StreamReader其实是一次性读取全部内容后,再切割成数组后返回其中某一行的。做个比方:
比如文件D:\test.txt中的内容是
1111111111111111111111\r\n
2222222222222222222222\r\n
程序代码:
StreamReader sr = new StreamReader(new FileStream(@"D:\test.txt",FileMode.Open,FileAccess.Read));
string a1 = sr.ReadLine();
sr.BaseStream.Seek(0,SeekOrigin.Begin);
string a2 = sr.ReadToEnd();
sr.Dispose();
结果:
变量a1的结果是正常的1111111111111111111111\r\n
照理说a2的结果应该是这样
1111111111111111111111\r\n
2222222222222222222222\r\n
但其实a2的结果是这样2222222222222222222222\r\n
1111111111111111111111\r\n
2222222222222222222222\r\n
因为读取一行后,虽然不在读取了,但其实后面的内容已经在输出的缓冲区间了。因为StreamReader的ReadLine是一次性读取的然后在判断某一行的,执行完ReadLine()以后,用断点就发现BaseStream.Position已经是在文件尾了。所以a2的结果就是 原来的内容加上从头又读取一次的全部内容。知道问题就好办了,虽然没有正规的解决办法还是可以通过ReadToEnd()来解决StreamReader sr = new StreamReader(new FileStream(@"D:\test.txt",FileMode.Open,FileAccess.Read));
string a1 = sr.ReadLine();
sr.ReadToEnd(); /// 在这里空读一下,这样就把剩余内容释放了。然后再重新读取。
sr.BaseStream.Seek(0,SeekOrigin.Begin);
string a2 = sr.ReadToEnd();
sr.Dispose();