字符集的前世今生

最早的是ASCII(美国信息互换标准码),使用7位bit表示一个字符。32到126是可打印字符。1967年,ISO推荐了一个ASCII的变种,视图为国际上解决

1981年,随着欧洲各国的计算机普及,IBM等机构对ASCII进行了各不相同的扩展,使用8位表示一个字符。共有256个。这被称为OEM字符集,事实上,当时大家对后面128为究竟该是什么都有不同意见。这在当时造成一定混乱。

1981年,中国国家标准总局发布了GB2312浸提中文字符集。使用2byte编码一个字符,包括6763个汉字。GB2312对汉字进行了分区处理,每个区有94个汉字。
01区到09区为特殊符号
16区到55区为一级汉字
56区到87区为二级汉子
10区15区,88区94区则没有编码。
这被称为区位码。比如汉字“啊”区位码为1601,因为他是16区的第一个汉字。在程序中,一般使用的是EUC-CN表示法。将高字节(第一个字节)和低字节(第二个字节)都加上A0,得出的0xB0A1就是“啊”的EUC-CN表示法下的GB2312编码。(一般浏览器中的GB2312都是指这个)。属于DBCS(双字节字符集)

历史上存在两个视图对世界文字进行统一编码的组织,分别为ISO(ISO/IEC 10646项目)和多语言软件制造商联盟(unicode项目)。二者1991开始合并对方的工作成果。顾名思义,前者为两个字节,后者为四个字节。在Unicode中为了节省空间,对中日韩(CJK)文字进行了统一编码。注意,unicode只是一个编码方案,而不是一个存储方案。 最大的编码值10FFFF。
在这里插入图片描述
Unicode包括UCS2和UCS4。UCS2在前面两个字节补零就得到了UCS4编码。显然,所有UCS2编码都可以转换成UCS4,而UCS4则不一定

1993年制订了 GB13000。相当于ISO/IEC 10646.1的中文版本。

1995年,全国信息技术委员会制订了GBK标准。也属于双字节字符集。

2000年,GB18030成为国家标准。采用了多字节编码(类似与下面所说的UTF8)。实际上,GB18030与其说是一种编码,倒不如说是对Unicode的一种转换编码(也就是UTF的一种)。此时,更加考虑的是GBK和GB2312的兼容。比如说本土软件要国际化,除了将现有的字符全部从GB2312换成Unicode,还可以直接升级为18030。这样,就有的字符不用变,而拥有了对Unicode中其他国家字符的使用能力。

UTF-8,UTF16,UTF32是针对Unicode的存储方案(也就是将编码数字转化为程序数据的方案,可以理解为对编码的编码)。所以GBK编码要转化为UTF8需要先转化为Unicode。

在这里插入图片描述

UTF以8为为单元为UCS进行编码,我们可以看一下下面的对应关系
UCS-2编码(16进制) UTF-8 字节流(二进制)
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
所以,不存在字节序的问题。但是UTF16以16bit为字符编码,判定的依据便是BOM.在发送字符之前,应该首先传送字符FEFF,这样接受者便知道是大端模式还是小端模式了。虽然说不需要,但是如果接受到EF BB BF开头的字节流。就表示为收到的是UTF-8的编码。
ASCII、GB2312、GBK到GB18030这些标准都是向下兼容的。UTF8只兼容ASCII

JAVA中的字符集

如果使用下面的代码,我的打印是

    public  static  void main(String[] args) {
        System.out.println( "当前JRE:" + System.getProperty( "java.version"));
        System.out.println( "当前JVM的默认字符集:" + Charset.defaultCharset());
        System.out.println(GBK.aa);
    }
当前JRE:1.8.0_151
当前JVM的默认字符集:UTF-8
�ߴ���

String自身是不保存自己的字符集的。所以,string内部存储的实际上.java文件中的直接量按照那个文件编码存储的二进制数组。在打印的时候根据控制台的编码格式就会出现乱码。
string里面除了byte数组,也会记录其编码格式。

    /**
     * The value is used for character storage.
     *
     * @implNote This field is trusted by the VM, and is a subject to
     * constant folding if String instance is constant. Overwriting this
     * field after construction will cause problems.
     *
     * Additionally, it is marked with {@link Stable} to trust the contents
     * of the array. No other facility in JDK provides this functionality (yet).
     * {@link Stable} is safe here, because value is never null.
     */
    @Stable
    private final byte[] value;

    /**
     * The identifier of the encoding used to encode the bytes in
     * {@code value}. The supported values in this implementation are
     *
     * LATIN1
     * UTF16
     *
     * @implNote This field is trusted by the VM, and is a subject to
     * constant folding if String instance is constant. Overwriting this
     * field after construction will cause problems.
     */
    private final byte coder;

    /** Cache the hash code for the string */
    private int hash; // Default to 0

java中约定,对于char,一个char包含两个byte。在存储中文上面是足够的。但是对于UCS4的某些字符,显然用一个char就做不了了。这时候就需要两个char才能表示一个字符。还好常见字符都是UCS2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值