Java 字符编码相关

Java String类型在内存中以unicode编码形式存储,unicode属于定长编码,便于管理,所以java采用了unicode。

 

getByte(String charset) 将unicode编码转换编译成指定编码

内部实现调用了encode方法

static byte[] encode(char[] ca, int off, int len) {
String csn = Charset.defaultCharset().name();  //获取系统默认编码
try {
return encode(csn, ca, off, len);  //安装指定编码方式对字符进行编码,如果是中文采用ISO8859-1,则无法编码,最后返回 "3f 3f"(两个问号)。

} catch (UnsupportedEncodingException x) {
warnUnsupportedCharset(csn);
}

//如果系统不支持系统默认编码,则用"ISO-8859-1
try {
return encode("ISO-8859-1", ca, off, len);
} catch (UnsupportedEncodingException x) {
// If this code is hit during VM initialization, MessageUtils is
// the only way we will be able to get any kind of error message.
MessageUtils.err("ISO-8859-1 charset not available: "
+ x.toString());
// If we can not find ISO-8859-1 (a required encoding) then things
// are seriously wrong with the installation.
System.exit(1);
return null;
}
}

字符编码转换时候常用到  public String(byte bytes[], String charsetName)  将字节数组按照charsetName编码进行组合识别,最后转换为unicode存储

该函数内部调用的StringCoding.decode(charsetName, bytes, offset, length);

原来认为该方法实现将bytes[]中的数据编码成指定的charsetName,但java实现的确实解码,即用指定的编码来读取bytes[]中的内容,也就是解码的意思,留空则采用系统默认的编码,如中文系统GBK

 

get方式传输参数乱码问题

原因:

1、chrome浏览器对问号后面的内容按照utf-8( firefox按照系统默认,中文系统一般gbk)进行编码

2、tomcat读取到的字节数组默认采用ISO8859-1编码(内存里是unicode),需要将其编码的数组转换成utf-8或者gbk方能正常显示中文

3、html没有以正确的编码方式显示。 如果html内容以gbk方式编码,但是meta 标签中content="text/html; charset=utf-8" ,即用utf-8解码gbk,必然出现问题。

Tomcat中URIEcoding 默认用ISO8859-1识别字符串,然后转成unicode存储在内存, ISO8859-1 是单字节编码,所以每个字节被按照原样 转换为unicode

String name = request.getParameter("name");
String name2 = new String(name.getBytes("ISO-8859-1"),"utf-8");
out.print(name2);

补充编码的一些知识:

当一个软件打开一个文本时,它要做的第一件事是决定这个文本究竟是使用哪种字符集的哪种编码保存的。软件有三种途径来决定文本的字符集和编码:
  最标准的途径是检测文本最开头的几个字节,如下表:
 
开头字节 Charset/encoding
EF BB BF    UTF-8
FE FF     UTF-16/UCS-2, little endian
FF FE     UTF-16/UCS-2, big endian
FF FE 00 00  UTF-32/UCS-4, little endian.
00 00 FE FF  UTF-32/UCS-4, big-endian. 
 
  例如插入标记后,连通”两个字的UTF-16 (big endian)和UTF-8码分别为:
FF FE DE 8F 1A 90
EF BB BF E8 BF 9E E9 80 9A
  但是MBCS文本没有这些位于开头的字符集标记,更不幸的是,一些早期的和一些设计不良的软件在保存Unicode文本时不插入这些位于开头的字符集标记。因此,软件不能依赖于这种途径。这时,软件可以采取一种比较安全的方式来决定字符集及其编码,那就是弹出一个对话框来请示用户,例如将那个“连通”文件拖到MS Word中,Word就会弹出一个对话框。
  如果软件不想麻烦用户,或者它不方便向用户请示,那它只能采取自己“猜”的方法,软件可以根据整个文本的特征来猜测它可能属于哪个charset,这就很可能不准了。使用记事本打开那个“连通”文件就属于这种情况。
  我们可以证明这一点:在记事本中键入“连通”后,选择“Save As”,会看到最后一个下拉框中显示有“ANSI”,这时保存。当再当打开“连通”文件出现乱码后,再点击“File”->“Save As”,会看到最后一个下拉框中显示有“UTF-8”,这说明记事本认为当前打开的这个文本是一个UTF-8编码的文本。而我们刚才保存时是用ANSI字符集保存的。这说明,记事本猜测了“连通”文件的字符集,认为它更像一个UTF-8编码文本。这是因为“连通”两个字的GB-2312编码看起来更像UTF-8编码导致的,这是一个巧合,不是所有文字都这样。可以使用记事本的打开功能,在打开“连通”文件时在最后一个下拉框中选择ANSI,就能正常显示了。反过来,如果之前保存时保存为UTF-8编码,则直接打开也不会出现问题。
  如果将“连通”文件放入MS Word中,Word也会认为它是一个UTF-8编码的文件,但它不能确定,因此会弹出一个对话框询问用户,这时选择“简体中文(GB2312)”,就能正常打开了。记事本在这一点上做得比较简化罢了,这与这个程序的定位是一致的。
 
http://www.cnblogs.com/lxzh/archive/2012/05/30/2526557.html 这篇文章不错
posted @ 2013-02-03 13:11  msober  阅读(1941)  评论(0编辑  收藏  举报