为什么是StreamReader和sr.BaseStream.Seek() 即使在 UTF8 编码中也能给出垃圾字符



abc.txt 文件内容是

ABCDEFGHIJ•XYZ

现在,如果我使用此代码(即寻求位置 9(,则显示的字符很好(,

string filePath = "D:\abc.txt";
FileStream fs = new FileStream(filePath, FileMode.Open);
StreamReader sr = new StreamReader(fs, new UTF8Encoding(true), true);
sr.BaseStream.Seek(9, SeekOrigin.Begin);
char[] oneChar = new char[1];
char ch = (char)sr.Read(oneChar, 0, 1);
MessageBox.Show(oneChar[0].ToString());

但是,如果 SEEK 位置就在那个特殊点字符之后,那么我就会得到垃圾字符。

所以,如果我确实寻求位置 11(即在点位置之后(,我会得到垃圾字符

sr.BaseStream.Seek(11, SeekOrigin.Begin);

这应该给出"X",因为第 11 位的字符是 X。

我认为文件内容在法律上是 UTF8。

还有一件事, StreamReader BaseStream 长度和 StreamReader Content Length 不同。

MessageBox.Show(sr.BaseStream.Length.ToString());
MessageBox.Show(sr.ReadToEnd().Length.ToString());

为什么是StreamReader和sr。BaseStream.Seek(( 即使在 UTF8 编码中也能提供垃圾字符

正是因为UTF-8,sr.BaseStream才给出了垃圾字符。 :)

StreamReader是一个相对"更智能"的流。它了解字符串的工作原理,而FileStream(即sr.BaseStream( 没有。FileStream只知道字节。

由于您的文件以 UTF-8(一种可变长度编码(编码,因此像ABC这样的字母使用 1 个字节进行编码,但字符需要 3 个字节。您可以通过执行以下操作来获取字符需要多少字节:

Console.WriteLine(Encoding.UTF8.GetByteCount("•"));

因此,当您将流移动到"紧随之后的位置"时,您实际上并没有经过,您只是在它的第二个字节上。

Lengths不同的原因是相似的:StreamReader给你字符数,而sr.BaseStream给你字节数。

最新更新