`

[Charset]UTF-8, UTF-16, UTF-16LE, UTF-16BE的区别

阅读更多
[Charset]UTF-8, UTF-16, UTF-16LE, UTF-16BE的区别

最近遇到的麻烦事
charset里的问题, 一般我们都用unicode来作为统一编码, 但unicode也有多种表现形式

首先, 我们说的unicode, 其实就是utf-16, 但最通用的却是utf-8,
原因: 我猜大概是英文占的比例比较大, 这样utf-8的存储优势比较明显, 因为utf-16是固定16位的(双字节), 而utf-8则是看情况而定, 即可变长度, 常规的128个ASCII只需要8位(单字节), 而汉字需要24位

UTF-16, UTF-16LE, UTF-16BE, 及其区别BOM
同样都是unicode, 为什么要搞3种这么麻烦?
先说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个再字节是很不流畅的

小结:
InputStreamReader reader=new InputStreamReader(fin, charset)

1. 如果这个UTF-16文件里带有BOM的话, charset就用"UTF-16", java会自动根据BOM判断LE还是BE, 如果你在这里指定了"UTF-16LE"或"UTF-16BE"的话, 猜错了会生成乱七八糟的文件, 哪怕猜对了, java也会把头2个字节当成文本输出给你而不会略过去, 因为[FF FE]或[FE FF]这2个代码没有内容, 所以, windows会用"?"代替给你
2. 如果这个UTF-16文件里不带BOM的话, 则charset就要用"UTF-16LE"或"UTF-16BE"来指定LE还是BE的编码方式


另外, UTF-8也有BOM的, [0xEF, 0xBB, 0xBF], 但可有可无, 但用windows的notepad另存为时会自动帮你加上这个, 而很多非windows平台的UTF8文件又没有这个BOM, 真是难为我们这些程序员啊

错误的例子
1. 文件A, UTF16格式, 带BOM LE,
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, - -#

6. 文件A, UTF16格式, BE 不带BOM,
InputStreamReader reader=new InputStreamReader(fin, "utf-16")
恭喜你, 蒙对了
但winodws的notepad打开时, 每个字符中间都多了一个" ", 因为notepad把它当成ASNI了

在windows下输出unicode文件
通过java出来unicode文件, 也容易混淆

FileOutputStream fout=new FileOutputStream(file);
OutputStreamWriter writer=new OutputStreamWriter(fout, charset);


1. charset为"UTF-16"时, java会默认添加BOM [0xFE, 0xFF], 并以BE的格式编写byte
2. charset为"UTF-16BE"时, java不会添加BOM, 但编码方式为 BE
3. charset为"UTF-16LE"时, java不会添加BOM, 但编码方式为 LE

以上通过 test.getByte("utf-16"), test.getByte("utf-16be"), test.getByte("utf-16le") 可以验证

而windows的notepad默认的unicode为 LE, 并带BOM,
所以, 推荐输出 UTF-16LE, 并人为添加BOM, 即:
byte[] bom={-1, -2};    //FF FE, java的byte用的是补码, 验证: b=127, b+=1, 而b=-128
fout.write(bom);




分享到:
评论
3 楼 thinkx 2010-02-20  
双字节最多为65000多个编码,世界上所有语言加在一起可不只这个数,所以utf-16是固定双字节应该是不对的,中文等常用语言的unicode编码可能在双字节范围内。
2 楼 骨之灵魂 2010-02-20  
"因为utf-16是固定16位的(双字节),"

不是这样哦
1 楼 Tomzheng 2010-02-20  
编码格式,utf-8比较好一点!谁叫汉语排后边了!哎

相关推荐

    Java判断文件的编码

    - 检查是否符合UTF-16LE、UTF-16BE和UTF-8的BOM特征,如果是则直接返回对应的编码格式。 3. **进一步检测**: - 如果前面的检查都没有发现有效编码,则进入循环,逐个字节检查。 - 循环中根据UTF-8的编码规则,...

    VBS实现GB2312,UTF-8,Unicode,BIG5编码转换工具

    这个VBS工具由两个脚本组成:GB2Ue.vbs和Ue2U8.vbs,分别用于GB2312到Unicode(UCS-2 Little Endian格式,通常简称为UTF-16LE)的转换和Unicode到UTF-8的转换。通过组合这两个脚本,可以实现GB2312到UTF-8以及其他...

    java获取文件编码(判断有无BOM)

    例如,UTF-8的BOM是三个字节(0xEF, 0xBB, 0xBF),而UTF-16LE和UTF-16BE的BOM分别是两个字节(0xFF, 0xFE)和(0xFE, 0xFF)。虽然UTF-8的BOM在很多情况下不是必须的,但有些软件可能会在创建文件时默认添加。 在...

    ASP生成UTF-8编码的代码

    该方法的第三个参数设置为`True`表示允许覆盖同名文件,而第四个参数也设置为`True`表示以Unicode格式(即UTF-16LE)保存文件。最后,通过`fp.Write`方法将内容写入文件。 ##### 参数详解 - `FileName`: 文件名...

    java中各种编码转换.pdf

    这个PDF文件中的代码示例提供了一个名为`ChangeCharset`的类,它包含了多种常见的字符编码转换方法,如US-ASCII、ISO-8859-1、UTF-8、UTF-16BE、UTF-16LE、UTF-16以及GBK。下面我们将详细讨论这些编码以及它们在Java...

    java程序判断文件编码的类型

    charset = "UTF-16LE"; checked = true; } // 检查UTF-16BE else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) { charset = "UTF-16BE"; checked = true; } // 检查UTF-8 else ...

    VB Text Encoding

    例如,UTF-8有特定的BOM签名(EF BB BF),而UTF-16LE和UTF-16BE分别以FF FE和FE FF开始。 总结,VB中处理文本编码的关键在于理解各种编码格式的特性,并选择合适的方法进行读取。通过ADODB.Stream、二进制读取和...

    Detect_CharSet.cpp

    在各个计算机中,生成的txt文件有可能是ANSI、UTF-8、UTF-16LE、UTF-16BE、带BOM的UTF-8等编码类型。这个示例程序自动检测txt文件的编码类型,并将其转换为ANSI编码。

    java去掉txt文本的bom头信息

    在UTF-16LE(小端序)中,它是FF FE,而在UTF-16BE(大端序)中则是FE FF。在UTF-32LE中,BOM头为FF FE 00 00,而UTF-32BE则是00 00 FE FF。 要从TXT文件中删除BOM头,我们可以使用Java的字节流和字符流进行操作。...

    自动编码识别 BOM

    熊猫看书作为一款阅读软件,能自动识别包括GBK、UTF8、UTF-16LE、UTF-16BE和BIG5在内的五种中国地区常见编码格式,从而确保用户能够顺利阅读各种类型的电子书。 对于含有BOM的TXT文件,识别编码相对简单。BOM位于...

    javascript js 对网页提交内容进行 md5加密 示例

    <meta charset="UTF-8"> <title>JavaScript MD5加密示例 <script src="md5.js"></script> 请输入内容"> ()">加密并显示 <p id="encryptedResult"></p> function encryptAndLog() { const content = ...

    字节流编码获取

    例如,UTF-16LE表示小端字节序,而UTF-16BE表示大端字节序。在处理这些编码的字节流时,正确识别BOM至关重要。 在实际编程中,处理字节流编码的关键步骤包括: 1. 打开一个输入流(如FileInputStream)。 2. 如果...

    ecl_array.js:ecl.js 基本字符集转换库

    Shift_JIS (CP932), EUC-JP, JIS (iso-2022-jp), UTF-8, UTF-16BE, UTF-16LE, UTF-7, Modified UTF-7的相互转换 逃脱/解脱 实现 Base64、URL 转义 (% XX)、Unicode 转义 (% uXXXX) 示例代码 // Javascript文字列を...

    Win32下HTTP请求

    在本例中,由于使用了UNICODE编码,即UTF-16LE,因此在与服务器交互时需要进行适当的编码转换。 在提供的头文件HttpHelper中,很可能包含了实现这些功能的函数或类。可能有如`SendHttpGetRequest`和`...

    文本文件编码方式区别

    - UTF-16:每个字符固定使用2字节(16位)存储,对于Unicode基本多文种平面( BMP)内的字符,UTF-16有两种字节顺序,小端序(LE,Little Endian)和大端序(BE,Big Endian)。UTF-16文件通常会有FE FF或FF FE作为...

    创建一个简单的圣诞树网页代码实现方式.docx

    DOCTYPE html> <html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Christmas Tree</title> <style> body { display: flex;...

    CodificaTesti:文本编码课程资料库

    例如,UTF-16LE(小端)和UTF-16BE(大端)。 8. **文本处理与编码**:在读取、写入或处理文本文件时,必须清楚其使用的编码,否则可能会出现解析错误。编程语言如Python、Java、C++都有相应的函数或库来处理编码...

    element vue validate验证名称重复 输入框与后台重复验证 特殊字符 字符长度 及注意事项小结【实例代码】

    meta charset=UTF-8> <title>Title</title> <link rel=stylesheet href=https://unpkg.com/element-ui/lib/theme-chalk/index.css rel=external nofollow > </head> <body > &...

    php检测文件编码的方法示例

    这个列表包括GBK、UTF-8、UTF-16LE、UTF-16BE和ISO-8859-1,这些是常见的文本编码格式。 ```php function detect_encoding($file) { $list = array('GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1'); $str...

    java读取文件字符集示例方法

    这三个字节通常包含了文件的字节序标记(BOM),对于UTF-16LE、UTF-16BE和UTF-8三种常见的Unicode字符集,BOM可以帮助我们快速识别字符集。 1. 如果`first3Bytes`的前两个字节是`FF FE`,则文件使用UTF-16LE(小端...

Global site tag (gtag.js) - Google Analytics