博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 小叙 Encoding (二)
阅读量:4973 次
发布时间:2019-06-12

本文共 5210 字,大约阅读时间需要 17 分钟。

Encoding用法

Encoding用法比较简单,如果只是字节和字符的互相转换,GetBytes()和GetChars()这两个方法及它们的重载基本上会满足你所有要求。

GetByteCount()及其重载是得到一个字符串转换成字节时实际的字节个数。

GetCharCount()及其重载是得到一个字节数组转换成字符串的大小。

要注意这两个方法:int GetMaxByteCount(int charCount); int GetMaxCharCount(int byteCount);

它并不是你期望的那样,如果是单字节就返回charCount,如果是双字节就返回chartCount*2,而是chartCount+1,(chartCount+1)*2。

Console.WriteLine("The max byte count is {0}.", Encoding.Unicode.GetMaxByteCount(10));            Console.WriteLine("The max byte count is {0}.", Encoding.ASCII.GetMaxByteCount(10));

上面的结果分别是22和11,而不是20,10。我在一篇英文博客里找到了原因,我英语不好,没有弄明白什么是high surrogate和low surrogate:

       For example, Encoding.GetEncoding(1252).GetMaxByteCount(1) returns 2.  1252 is a single byte code page (encoding), so generally one would expect that GetMaxByteCount(n) would return n, but it doesn't, it usually returns n+1.

     One reason for this oddity is that an Encoder could store a high surrogate on one call to GetBytes(), hoping that the next call is a low surrogate.  This allows the fallback mechanism to provide a fallback for a complete surrogate pair, even if that pair is split between calls to GetBytes().  If the fallback returns a ? for each surrogate half, or if the next call doesn't have a surrogate, then 2 characters could be output for that surrogate pair.  So in this case, calling Encoder.GetBytes() with a high surrogate would return 0 bytes and then following that with another call with only the low surrogate would return 2 bytes.

下面代码是Encoding的简单应用,大家可以打印一下结果,然后结合上篇讲的,会有所收获的。

static void Output(Encoding encoding,string t)        {            Console.WriteLine(encoding.ToString());            byte[] buffer = encoding.GetBytes(t);            foreach (byte b in buffer)            {                Console.Write(b + "-");            }            string s = encoding.GetString(buffer);            Console.WriteLine(s);        }
string strTest = "test我镕a有κ";            Console.WriteLine(strTest);            Output(Encoding.GetEncoding("gb18030"), strTest);            Output(Encoding.Default, strTest);            Output(Encoding.UTF32, strTest);            Output(Encoding.UTF8, strTest);            Output(Encoding.Unicode, strTest);            Output(Encoding.ASCII, strTest);            Output(Encoding.UTF7, strTest);

关于BOM

BOM全称是Byte Order Mark,即字节顺序标记,是一段二进制,用于标识一个文本是用什么编码的,比如当用Notepad打开一个文本时,如果文本里包括这一段BOM,那么它就能判断是采用哪一种编码方式,并用相应的解码方式,就会正确打开文本不会有乱码。如果没有这一段BOM,Notepad会默认以ANSI打开,这种会有乱码的可能性。可以通过Encoding的方法GetPreamble()来判断这编码有没有BOM,目前CLR中只有下面5个Encoding有BOM。

UTF-8: EF BB BF

UTF-16 big endian: FE FF

UTF-16 little endian: FF FE

UTF-32 big endian: 00 00 FE FF

UTF-32 little endian: FF FE 00 00

用Encoding的静态属性Unicode,UTF8,UTF32构造的Encoding都是默认带有BOM的,如果你想在写一个文本时(比如XML文件,如果有BOM,会有乱码的),不想带BOM,那么就必须用它们的实例,

Encoding encodingUTF16=new UnicodeEncoding(false, false);//第二个参数必须要为falseEncoding encodingUTF8=new UTF8Encoding(false);Encoding encodingUTF32=new UTF32Encoding(false,false);//第二个参数必须要为false

 读写文本和BOM的关系可以参考园子里这篇博客,讲的很详细我就不重复了,

 判断一个文本的编码方式

如果给定一个文本,我们不知道它的编码格式,解码时我们如何选择Encoding呢?答案是根据BOM来判断到底是哪种Unicode,如果没有BOM,这个就很难说了,这个得根据文本文件的来源了,一般是用Encoding.Default,这个是根据你计算机里当前的设置而返回不同的值。如果你的文件是来自一位国际友人的话,你最好用UTF-8来解码了。下面的代码在指定文件没有BOM时,不能保证其正确性,如果你要用到你项目中,千万要注意这一点。

///         ///Return the Encoding of a text file.  Return Encoding.Default if no Unicode        // BOM (byte order mark) is found.        ///         ///         /// 
public static Encoding GetFileEncoding(String FileName) { Encoding Result = null; FileInfo FI = new FileInfo(FileName); FileStream FS = null; try { FS = FI.OpenRead(); Encoding[] UnicodeEncodings = { Encoding.BigEndianUnicode, Encoding.Unicode, Encoding.UTF8, Encoding.UTF32, new UTF32Encoding(true,true) }; for (int i = 0; Result == null && i < UnicodeEncodings.Length; i++) { FS.Position = 0; byte[] Preamble = UnicodeEncodings[i].GetPreamble(); bool PreamblesAreEqual = true; for (int j = 0; PreamblesAreEqual && j < Preamble.Length; j++) { PreamblesAreEqual = Preamble[j] == FS.ReadByte(); } // or use Array.Equals to compare two arrays. // fs.Read(buf, 0, Preamble.Length); // PreamblesAreEqual = Array.Equals(Preamble, buf) if (PreamblesAreEqual) { Result = UnicodeEncodings[i]; } } } catch (System.IO.IOException ex) { throw ex; } finally { if (FS != null) { FS.Close(); } } if (Result == null) { Result = Encoding.Default; } return Result; }

待续。。。。

下一节主要讲Encoder和Decoder

顺便问一下,编辑博客时,看着还挺漂亮的文章,怎么预览时好多格式都不见了?好难看啊

转载于:https://www.cnblogs.com/criedshy/archive/2012/08/07/2626415.html

你可能感兴趣的文章
寻找二叉查找树中比指定值小的所有节点中最大的那个节点
查看>>
如何设置输入框达到只读效果
查看>>
RT3070 USB WIFI 在连接socket编程过程中问题总结
查看>>
MIS外汇平台荣获“2013年全球最佳STP外汇交易商”
查看>>
LeetCode 题解之Add Digits
查看>>
hdu1502 , Regular Words, dp,高精度加法
查看>>
SpringBoot在idea中的热部署配置
查看>>
MyEclipse连接SQL Server 2008数据库的操作方法
查看>>
JS验证图片格式和大小并预览
查看>>
laravel5.2 移植到新服务器上除了“/”路由 ,其它路由对应的页面显示报404错误(Object not found!)———新装的LAMP没有加载Rewrite模块...
查看>>
编写高质量代码--改善python程序的建议(六)
查看>>
windows xp 中的administrator帐户不在用户登录内怎么解决?
查看>>
接口和抽象类有什么区别
查看>>
Codeforces Round #206 (Div. 2)
查看>>
**p
查看>>
优先队列详解
查看>>
VS2012 创建项目失败,,提示为找到约束。。。。
查看>>
设计类图
查看>>
类对象
查看>>
[Voice communications] 声音的滤波
查看>>