关于 StreamReader 逐字读取字符的问题
2008-06-03 23:47 晓风残月 阅读(4984) 评论(30) 编辑 收藏 举报MSDN 对 StreamReader.Read() 方法的解释是:
读取输入流中的下一个字符并使该字符的位置提升一个字符。
而该方法的返回值是一个 int ,之前竟然是这样转换的:
string str =System.Text.Encoding.Unicode.GetString(BitConverter.GetBytes(sr.Read()));
还是费了九牛二虎之力,才得到正确结果,才发现无论使用何种Encoding打开Stream,返回的总是 Unicode 编码。
今天才发现:可以直接将 int 强制转换成 char,并且可以正确的解码。因为,上面提到 Read 总是返回 Unicode 编码,而 char 在 .NET 内部正是用的 Unicode 编码。
char ch = (char)sr.Read();
事实上,MSDN这句话出现了两处字符已经暗示了 char 类型,只怪自己未能领悟。那么为什么 Read() 方法不直接返回 char ?StreamReader 的基类 TextReader 就是明确定义为字符的读取器。 找到MSDN对char类型的说明中提到:
多数 Unicode 字符可由一个 Char 对象表示,但编码为基字符、代理项对和/或组合字符序列的字符由多个 Char 对象表示。因此,String 对象中的 Char 结构不一定与单个 Unicode 字符等效。
看样子,返回 int 类型是为了兼容双字节(char为双字节)仍能无法表示的字符,只是此时就不知道怎么转换了? 用第一种方法强制解码?
有空找几个特殊字符来试试~
以下示例代码使用了GB2312作为流编码,当然其他编码也是一样的。
public string Foo(string path) { StringBuilder outBuffer = new StringBuilder(); try { if (File.Exists(path)) { File.Delete(path); } Encoding fileEncoding = Encoding.GetEncoding("GB2312"); using (StreamWriter sw = new StreamWriter(path, false, fileEncoding)) { sw.WriteLine("我"); sw.WriteLine("是"); sw.WriteLine("中国人"); } using (StreamReader sr = new StreamReader(path, fileEncoding)) { while (sr.Peek() >= 0) { // 曾经是这样读取的:将 int 转成 byte[],然后再解码,然后尝试了N多编码, //费了九牛二虎之力,才得到正确结果,才发现无论使用何种Encoding打开Stream,返回的总是 Unicode 编码。 // outBuffer.Append(System.Text.Encoding.Unicode.GetString(BitConverter.GetBytes(sr.Read()))); // // 今天才在MSDN中发现:可以直接将 int 强制转换成 char,并且可以正确的解码。 // 因为,上面提到 Reader 总是返回 Unicode 编码,而 char 在 .NET 内部正是用的 Unicode 编码。 // 郁闷! outBuffer.Append((char)sr.Read()); } } } catch (Exception ex) { outBuffer.AppendFormat("The process failed: {0}", ex.ToString()).AppendLine(); } // return outBuffer.ToString(); }