`

[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比较好一点!谁叫汉语排后边了!哎

相关推荐

    Detect_CharSet.cpp

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

    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文字列を...

    phpmailer中文乱码问题的解决方法

    改为 public $CharSet = ‘UTF-8′; 至于为什么要将’iso-8859-1′改为‘UTF-8’,请google或百度一下’iso-8859-1′就清楚。 2:设置邮件的编码; 复制代码 代码如下:$mail = new PHPMailer();$mail->Charset=’...

    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 > &...

    html table实现复杂表头的示例代码

    复杂表格一般是用到td的两个属性:rowspan 、colspan属性值。 ... charset=utf-8" /> <title>多表头表格</title> </head> <body> <table id="tab" cellpadding="1

    bootstrap制作jsp页面(根据值让table显示选中)

    本文实例为大家分享了bootstrap制作... charset=UTF-8 pageEncoding=UTF-8%> <%@include file=/views/resource.jsp%> <body style=background-color: transparent;> <div id=leftlist class=page

    PHPMailer使用教程(PHPMailer发送邮件实例分析)

    charset=utf-8”); ini_set(“magic_quotes_runtime”,0); require ‘class.phpmailer.php’; try { $mail = new PHPMailer(true); $mail->IsSMTP(); $mail->CharSet=’UTF-8′; //设置邮件的字符编码,这很重要,...

    php.ini-development

    directive because it is not set or is mistyped, a default value will be used. ; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one ; of the INI constants (On, Off, True, ...

    angularjs表格ng-table使用备忘录

    项目中用到angularjs的表格ng-table,功能相当强大,像搜索、排序、checkbox、分页、每页表格显示数目等...meta charset="utf-8"/> <head> [removed][removed] <script data-require="ng-table@*" data-

    extmail 1.1

    o Fully UTF-8 and multi-charset conversion support, eg CJK. o Small code size and tidy, use perl OO design o Small memory and cpu footprint, suitable for ISP o IMAP4v1 modified UTF-7 folder and...

    详解Bootstrap的aria-label和aria-labelledby应用

    meta charset = utf-8> <title>demo</title> <link href=bootstrap-3.3.4-dist/css/bootstrap.min.css rel=stylesheet> <style type=text/css> body{padding: 20px;} </style&gt...

    用jquery获取select标签中选中的option值及文本的示例

    charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <script type="text/...

    AngularJS基础 ng-disabled 指令详解及简单示例

    meta charset="utf-8"> [removed][removed] </head> <body ng-app=""> 点击这里禁用所有表单输入域:<input type="checkbox" ng-model="all"> <input type="text" ng-disab

    CSS flex-basis 文本溢出问题的解决

    不值一提的 flex-basis ,却给文本溢出添加省略号这个小小的功能带来很多了麻烦。下面来演示一下。 1. flex 家族 flex 里有很多的属性,我们经常用到的就是如下操作: .container { ...meta charset=UTF-8 /

    JavaScript实现星星等级评价功能

    meta charset=UTF-8> <title>Document</title> <style> .container{ float:left; } .score{ float: left; position: relative; width: 100px; margin-top: 5px; margin-le

    CSS通过letter-spacing属性 控制字与字间隔

    meta charset="UTF-8"> <title>Insert title here</title> <style type="text/css"> span{ letter-spacing: 10px; } </style> </head> <body> 测试字间距</spa

    layui-tree实现Ajax异步请求后动态添加节点的方法

    最近在弄一个产品分类管理,是一个树形菜单的形式,用的是layui-tree ,由于它并没有动态添加节点,所以只能自己刚了。...meta charset="UTF-8"> <title>多级分类管理</title> <meta name="r

    PHP Google的translate API代码

    charset=utf-8”); class Google_API_translator{ public $opts = array(“text” => “”, “language_pair” => “en|it”); public $out = “”; function setOpts($opts) { if($opts[“text”] != “”) $this-...

    Angularjs 动态改变title标题(兼容ios)

    废话不多说了,直接给大家贴代码了,具体代码如下所示: <pre name=code class=javascript>angular.module('myApp.loginCtrl', []) ...charset=utf-8'; //改变header中content-type的格式 }) .controller('loginCtrl'

    基于javascipt-dom编程 table对象的使用

    排名练习:向表格添加数据,当编号遇到重复给予提示并且无法添加,而且按排名顺序添加数据 参考代码: 代码如下:<...charset=utf-8″><!–js代码可以放置在任意位置,按照先后顺序依次执行 一般放在head标签

Global site tag (gtag.js) - Google Analytics