本文粗略了解下常用的编码方式。
众所周知,Java的char型占用两个字节,采用了Unicode编码方式的UTF-16实现。
iso8859-1
属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列。比如,字母’a’的编码为0x61=97。
很明显,iso8859-1编码表示的字符范围很窄,无法表示中文字符。但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,仍旧使用iso8859-1编码来表示。而且在很多协议上,默认使用该编码。比如,虽然”中文”两个字不存在iso8859-1编码,以gb2312编码为例,应该是”d6d0 cec4”两个字符,使用iso8859-1编码的时候则将它拆开为4个字节来表示:”d6 d0 ce c4”(事实上,在进行存储的时候,也是以字节为单位处理的)。而如果是UTF编码,则是6个字节”e4 b8 ad e6 96 87”。很明显,这种表示方法还需要以另一种编码为基础。
GB2312/GBK
这就是汉字的国标码,是双字节编码,而英文字母兼容iso8859-1编码。其中GBK编码能够用来同时表示繁体字和简体字,而GB2312只能表示简体字,GBK是兼容GB2312编码的。
unicode
是定长双字节的编码,想要表示世界上所有的语言文字,独成一个体系,不兼容其他编码。在我理解,它像一个标准,而常见的UTF规范包括UTF-8、UTF-16、UTF-32是对它的一种实现。
对于UTF-8,英文字母都是用一个字节表示,而汉字使用三个字节,所以在HTML文件传输中,一般英文字母比较多,UTF-8是比较节省的。
一个例子
package com.leo.character;
/**
* 字符集的初探
* Created by Leo on 2017/4/9.
*/
public class Main {
public static void main(String[] args) throws Exception {
//表明一个char占用两个字节
char aChar = '中';
System.out.println(Integer.toHexString(aChar));//输出:4e2d
System.out.println("--------------------------------------");
String a = "中";
System.out.println(bytesToHexString(a.getBytes()));//输出:e4b8 ad String.getBytes()默认采用本OS支持的编码方式
System.out.println(bytesToHexString(a.getBytes("unicode")));//输出:feff 4e2d 为什么前面有feff不理解
System.out.println(bytesToHexString(a.getBytes("utf-16")));//输出:feff 4e2d 可以看出java默认采用unicode的utf-16实现
System.out.println(bytesToHexString(a.getBytes("utf-8")));//输出:e4b8 ad
System.out.println(bytesToHexString(a.getBytes("GBK")));//输出:d6d0
System.out.println(bytesToHexString(a.getBytes("iso8859-1")));//输出:3f ?表示没有对应的编码
String aa = "中文";
System.out.println(bytesToHexString(aa.getBytes()));//输出:e4b8 ad
System.out.println(bytesToHexString(aa.getBytes("unicode")));//输出:feff 4e2d 6587
System.out.println(bytesToHexString(aa.getBytes("utf-16")));//输出:feff 4e2d 6587
System.out.println(bytesToHexString(aa.getBytes("utf-8")));//输出:e4b8 ade6 9687
System.out.println(bytesToHexString(aa.getBytes("GBK")));//输出:d6d0 cec4
System.out.println(bytesToHexString(aa.getBytes("iso8859-1")));//输出:3f3f
}
/* *
* 输出byte数组的十六进制表示
*Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)
*来转换成16进制字符串。
* @param src byte[] data
* @return hex string
*/
public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
if ((i % 2) == 0 && i > 0) stringBuilder.append(" ");//每两个字节打一个空格
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}