Java中字符编码总结

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

文章目录

字符/字符编码/字符集 概念

字符:在计算机和电信技术中,一个字符是一个单位的字形、类字形单位或符号的基本信息。即一个字符可以是一个中文汉字、一个英文字母、一个阿拉伯数字、一个标点符号等。

字符集:多个字符的集合。例如 GB2312 是中国国家标准的简体中文字符集,GB2312 收录简化汉字(6763个)及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 个图形字符。

字符编码:把字符集中的字符编码为(映射)指定集合中的某一对象(例如:比特模式、自然数序列、电脉冲),以便文本在计算机中存储和通过通信网络的传递。

字符集和字符编码的关系
字符集是书写系统字母与符号的集合,而字符编码则是将字符映射为一特定的字节或字节序列,是一种规则。通常特定的字符集采用特定的编码方式(即一种字符集对应一种字符编码(例如:ASCII、IOS-8859-1、GB2312、GBK,都是既表示了字符集又表示了对应的字符编码,但Unicode不是,它采用现代的模型)),因此基本上可以将两者视为同义词。

常见编码字符集

  • ASCII
    American Standard Code for Information Interchange 即美国标准信息交换代码。早期的计算机系统只能处理英文,所以 ASCII 也就成为了计算机的缺省字符集,只包含英文字母和常用字符。
  • ISO-8859-1
    也称为Latin1,西欧编码表。128-255 之间的字符用于拉丁字母表中特殊语言字符的编码。向下兼容ASCII,其编码范围是 0x00-0xFF(0-255),0x00-0x7F(0-127)之间完全和 ASCII 一致
  • GB2312
    GB 是"国标"的拼音缩写,2312 是国标序号。中文字符集,包含ASCII字符集。ASCII部分用单字节表示,剩余部分用双字节表示。
  • GBK
    GBK即"国标扩展"汉语拼音的第一个字母,是GB2312的扩展,完整包含了GB2312的所有内容。GBK 标准中收录了 21003 个汉字及符号,通常把 GB2312 中的这 6763 字称为"常用字",而将包含在 GBK 而不包含在 GB2312 字符集内的汉字称为"生僻字"。

由此可知,一般而言,最常用的中文编码就是GBK。

  • BIG5
    大五码,是通行于台湾、香港地区的一个繁体字编码方案。
  • Unicode
    Unicode(统一码、万国码、单一码)是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

Unicode传输格式
因为 Unicode 码中,我们一般只使用常用字符表,用 2 个字节表示的,因此会有一个问题,如果采用其他编码格式,英文是单字节表示的,但采用 Uincode 存储,存储量会翻倍。在 Unicode 字典中往后的字符可能就需要 3 个字节或者 4 个字节,甚至更多字节来表示了。为了较好的解决 Unicode 的编码问题, UTF-8 和 UTF-16 两种当前比较流行的编码方式诞生了。

常用的是UTF-8。英文,单字节;某些字符,双字节;中文,3 字节。

java对字符的处理

在 java 应用软件中,会有多处涉及到字符集编码,有些地方需要进行正确的设置,有些地方需要进行一定程度的处理。

1、getBytes(charset)
这是 java 字符串处理的一个标准函数,其作用是将字符串所表示的字符按照 charset 编码,并以字节方式表示。注意:字符串在 java 内存中总是按 unicode 编码存储的。

2、new String(charset)
这是 java 字符串处理的另一个标准函数,和上一个函数的作用相反,将字节数组按照 charset 编码进行组合识别,最后转换为 unicode 存储。

3、setCharacterEncoding()
该函数用来设置 http 请求或者相应的编码。

java 字符编码转换

1、unicode 编码转换成其他编码

String s = "abc中文";
//如果不指定,则由Unicode编码转为默认编码
//window中文系统默认GBK
//android手机默认UTF-8
byte[] a = s.getBytes();
//转成指定编码
byte[] a = s.getBytes("UTF-8");
复制代码

2、其他编码转换成 unicode 编码

//从默认编码转为unicode
String s = new String(a);
//从指定编码转为unicode
String s = new String(a,"UTF-8");
复制代码

3、输出默认编码

String defaultCharsetName = Charset.defaultCharset().displayName();
System.out.println("defaultCharsetName:" + defaultCharsetName);
复制代码

运行程序我们看到默认是:
在这里插入图片描述

栗子1

public class Main {
    public static void main(String[] args) throws Exception {
        String s = "abc中文喆镕";
        System.out.println(s);

        f(s);
        f(s, "GBK");
        f(s, "GB2312");
        f(s, "UTF-8");
    }

    private static void f(String s) {
        // unicode->默认
        byte[] a = s.getBytes();
        System.out.println("默认:\t" + Arrays.toString(a));
    }

    private static void f(String s, String charset) throws Exception {
        // unicode->指定编码
        byte[] a = s.getBytes(charset);
        System.out.println(charset + "\t" + Arrays.toString(a));
    }
}
复制代码

运行结果:
在这里插入图片描述
结果分析

abc中文喆镕
默认:	[97, 98, 99, -28, -72, -83, -26, -106, -121, -27, -106, -122, -23, -107, -107]
默认UTF-8
GBK	[97, 98, 99, -42, -48, -50, -60, -122, -76, -23, 70]
英文一个字节,中文2个字节
GB2312	[97, 98, 99, -42, -48, -50, -60, 63, 63]
前面是一样的,GB2312中不包含“喆”和“镕”,其中63表示?
UTF-8	[97, 98, 99, -28, -72, -83, -26, -106, -121, -27, -106, -122, -23, -107, -107]
英文一个字节,中文3个字节
复制代码

栗子2

public class Main {
    public static void main(String[] args) throws Exception {
        byte[] a;

        a = new byte[]{97, 98, 99, -28, -72, -83, -26, -106, -121, -27, -106, -122, -23, -107, -107};
        f(a);

        //GBK编码转为unicode编码
        a = new byte[]{97, 98, 99, -42, -48, -50, -60, -122, -76, -23, 70};
        f(a, "GBK");

        //GB2312转unicode编码
        a = new byte[]{97, 98, 99, -42, -48, -50, -60, 63, 63};
        f(a, "GB2312");

        //utf-8转unicode编码
        a = new byte[]{97, 98, 99, -28, -72, -83, -26, -106, -121, -27, -106, -122, -23, -107, -107};
        f(a, "UTF-8");
    }

    private static void f(byte[] a) {
        // 默认编码——>Unicode
        String s = new String(a);
        System.out.println("默认:\t" + s);
    }

    private static void f(byte[] a, String charset) throws Exception {
        // 指定编码——>unicode
        String s = new String(a, charset);
        System.out.println(charset + "\t" + s);
    }
}
复制代码

运行结果
在这里插入图片描述

更多查看: Java字符编码原理总结

猜你喜欢

转载自juejin.im/post/7018061233785929765