[面试系列] java 字符编码

5 篇文章 0 订阅

开头

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

 

概念

说道编码,必须先明白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      编码的一系列文章

          http://blog.csdn.net/jiangfuqiang/article/details/17222255    4字节UTF16编码和对C++/Java的影响

          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值