null UTF-16是Unicode的其中一个使用方式。 UTF是 Unicode Translation Format,即把Unicode转做某种格式的意思。 它定义于ISO/IEC 10646-1的附录Q,而RFC2781也定义了相似的做法。 在Unicode基本多文种平面定义的字符(无论是拉丁字母、汉字或其他文字或符号),一律使用2字节储存。而在辅助平面定义的字符,会以代理对(surrogate pair)的形式,以两个2字节的值来储存。 UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节 (2字节) 储存,但UTF-16却无法兼容于ASCII编码。c#中默认的就是UTF-16,所以在处理c#字符串的时候只能是bety,stream等方式去处理
UTF-16的大尾序和小尾序储存形式都在用。一般来说,以Macintosh制作或储存的文字使用大尾序格式,以Microsoft或Linux制作或储存的文字使用小尾序格式。
null为了弄清楚UTF-16文件的大小尾序,在UTF-16文件的开首,都会放置一个U+FEFF字符作为Byte Order Mark(UTF-16LE以FF FE代表,UTF-16BE以FE FF代表),以显示这个文字档案是以UTF-16编码,其中U+FEFF字符在UNICODE中代表的意义是ZERO WIDTH NO-BREAK SPACE,顾名思义,它是个没有宽度也没有断字的空白。
UTF-16BE (big endian), 比较好理解的, 俗称大头 比如说char 'a', ascii为
0x61, 那么它的utf-8, 则为 [0x61], 但utf-16是16位的, 所以为[0x00, 0x61] 再说UTF-16LE(little endian), 俗称小头, 这个是比较常用的
还是char 'a', 它的代码却反过来: [0x61, 0x00], 据说是为了提高速度而迎合CPU的胃口, CPU就是这到倒着吃数据的, 这里面有汇编的知识,UTF-16, 要从代码里自动判断一个文件到底是UTF-16LE还是BE, 对于单纯的英文字符来说还比较好办, 但要有特殊字符, 图形符号, 汉字, 法文, 俄语, 火星语之类的话, 相信各位都很头痛吧, 所以, unicode组织引入了BOM的概念, 即byte order mark, 顾名思义, 就是表名这个文件到底是LE还是BE的,
其方法就是, 在UTF-16文件的头2个字节里做个标记: LE [0xFF, 0xFE], BE [0xFE, 0xFF]
理解了这个后, 在java里遇到utf-16还是会遇到麻烦, 因为要在文件里面单独判断头2个再字节是很不流畅的 。
如果这个UTF-16文件里带有BOM的话, charset就用"UTF-16", java会自动根据BOM判断LE还是BE, 如果你在这里指定了"UTF-16LE"或"UTF-16BE"的话, 猜错了会生成乱七八糟的文件, 哪怕猜对了, java也会把头2个字节当成文本输出给你而不会略过去, 因为[FF FE]或[FE FF]这2个代码没有内容,另外, UTF-8也有BOM的, [0xEF, 0xBB, 0xBF], 但可有可无, 但用windows的notepad另存为时会自动帮你加上这个, 而很多非windows平台的UTF8文件又没有这个BOM
1. 文件A, UTF16格式, 带BOM LE,
null
InputStreamReader reader=new InputStreamReader(fin, "utf-16le") 会多输出一个"?"在第一个字节, 原因: java没有把头2位当成BOM
2. 文件A, UTF16格式, 带BOM LE,
InputStreamReader reader=new InputStreamReader(fin, "utf-16be")
会出乱码, 原因: 字节的高低位弄反了, 'a' 在文件里 [0x61, 0x00], 但java以为'a'应该是[0x00 0x61]
3. 文件A, UTF16格式, 带BOM BE,
InputStreamReader reader=new InputStreamReader(fin, "utf-16le")
会出乱码, 原因: 字节的高低位弄反了, 'a' 在文件里 [0x00, 0x61], 但java以为'a'应该是[0x61 0x00]
4. 文件A, UTF16格式, 带BOM BE,
InputStreamReader reader=new InputStreamReader(fin, "utf-16be") 会多输出一个"?"在第一个字节, 原因: java没有把头2位当成BOM
5. 文件A, UTF16格式, LE 不带BOM,
InputStreamReader reader=new InputStreamReader(fin, "utf-16") 会出乱码, 因为utf-16对于java来说, 默认为be(1.6JDK, 以后的说不准) 但windows的notepad打开正常, 因为notepad默认为le, - -#