您的位置:首页 > 职场人生

[面试系列] java 字符编码

2015-06-05 17:51 537 查看
开头

曾经面试,被问到字符编码的相关事项。现在总结一下, 避免在被问到。同时,也希望可以和大家一起研究一下编码的机制。

概念

说道编码,必须先明白3个概念。

1字符集:就是字符。如ASCII 字符集,包括: 大写的A,小写的a等。

2被编码的字符集:有了字符集,人们习惯给它们编个码。 比如:大写的A 对应的码是“41”(41 是 十六进制), 为了避免混淆, 下文中称为“编号”。

3字符集编码:字符集的计算机编码。

字符集和被编码的字符集,是在计算机出现前就有了,和计算机没有关系。 后来计算机出现了,只能存储多个0和1,怎么把字符集存到计算机中呢?字符集编码就是干这个事情的。

例子

我们举两个例子:

1) ASCII字符集:大写的字符‘A’--》编号为41--》编码后存入计算机中为41 41是十六进制

2) Unicode字符集:汉字“我” --》编号为 6211 --》 uft-8编码后: 3个字节 E68891

--》 uft-16编码后: 2个字节 FEFF6211, 注意, 这个FEFF, 表示的是utf-16的编码顺序。

--》 uft-32编码后: 4个字节 00006211

注意:unicode 对应一唯一一个被编码的字符集(编号), 但是对应多个编码方式(字符集编码),如uft-8, utf-16和utf-32.

程序运行结果的分析

一个例子程序结果: 该程序测试了“我”字的编码。

我-字的java内存表示-6211 注解:java内部使用utf-16编码

ISO-8859-1--------------------编码后1字节

3F

GB2312--------------------编码后2字节

CED2

utf-8--------------------编码后3字节

E68891

utf-16--------------------编码后4字节 注解:应该是两字节:6211. FEFF是编码的顺序。

FEFF6211

utf-32--------------------编码后4字节

00006211

GB18030--------------------编码后2字节

CED2

程序代码

测试代码:

package test.charset;

import java.io.UnsupportedEncodingException;

public class TestCharSetFor1 {

public static void main(String[] args) {
//String s = "I am 君山"; //即将被编码的字符串         java 使用unicode字符集合, utf-16 编码来内部存储的
String s = "我"; //即将被编码的字符串         java 使用unicode字符集合, utf-16 编码来内部存储的
char[] sc = s.toCharArray();
System.out.println(s + "-字的java内存表示-" +CharsetUtil.bytes2HexString(charsToBytes(sc)));
encodingBy(s, "ISO-8859-1");
encodingBy(s, "GB2312");
encodingBy(s, "utf-8");
encodingBy(s, "utf-16");
encodingBy(s, "utf-32");
encodingBy(s, "GB18030");
}

private static byte[] charsToBytes(char[] sc){
byte[] bs = new byte[sc.length * 2];
for (int i = 0; i < sc.length; i++) {
char c = sc[i];
byte tm1 = (byte)((c >> 8) & 0xff);
byte tm2 = (byte)(c & 0xff);
bs[2*i] = tm1;
bs[2*i + 1] = tm2;
}
return bs;
}

private static void encodingBy(String s, String charset) {
try {
byte[] bs1 = s.getBytes(charset);
printA(bs1, charset);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}

public static void printA(byte[] bs1, String charset){
System.out.println(charset + "--------------------编码后"+ bs1.length +"字节");
System.out.println(CharsetUtil.bytes2HexString(bs1));
}

}


package test.charset;

public class CharsetUtil {
/**
* 把byte[] 以十六进制输出
* @param b
* @return
*/
public static String bytes2HexString(byte[] b){
String ret="";
for (int i = 0; i < b.length; i++) {
ret += byte2HexString(b[i]);
}
return ret;
}

/**
* 把byte 以十六进制输出
* @param b
* @return
*/
public static String byte2HexString(byte b){
String ret = "";
String hex = Integer.toHexString(b & 0xFF);
if(hex.length() == 1){
hex = '0' + hex;
}
ret += hex.toUpperCase();
return ret;
}
public static void main(String[] args) {
System.out.println(bytes2HexString("m".getBytes()));
}
}


参考
http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 深入分析 Java 中的中文编码问题

http://my.oschina.net/goldenshaw/blog?catalog=536953 编码的一系列文章

/article/9648213.html 4字节UTF16编码和对C++/Java的影响
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: