中文字符与编码格式占位问题

最近面试,碰到的面试题。面试

Q:中文字符在UTF-8占几个字节?UTF-8是固定字长编码仍是动态字长编码的?windows

A:UTF-8编码下一个中文所占字节也是不肯定的。多是2个、3个、4个字节。所以可见UTF-8是变长的编码格式的。网络

 

扩展讲解

先从字符编码讲起编码

一、美国人首先对其英文字符进行了编码,也就是最先的ASCII码,用一个字节的低7位来表示英文的128个字符,高1位统一为0spa

二、后来欧洲人发现尼玛你这128位哪够用,好比我高贵的法国人字母上面的还有注音符,这个怎么区分?得,把高1位编进来吧,这样欧洲广泛使用一个全字节进行编码,最多可表示256位。欧美人就是喜欢直来直去,字符少,编码用得位数少翻译

三、可是即便位数少,不一样国家地区用不一样的字符编码,虽然0--127表示的符号是同样的。可是128--255这一段的解释彻底乱套了,即便2进制彻底同样,表示的字符彻底不同。好比135在法语,希伯来语,俄语编码中彻底是不一样的符号。更麻烦的是,尼玛这电脑高科技传到中国后,中国人发现咱们有10万多个汉字,大家欧美这256字塞牙缝都不够。因而就发明了GB2312这些汉字编码,典型的用2个字节来表示绝大部分的经常使用汉字,最多能够表示65536个汉字字符,这样就不难理解有些汉字你在新华字典里查获得,可是电脑上若是不处理一下你是显示不出来的了吧设计

四、这下各用各的字符集编码,这世界咋统一?
俄国人发封Email给中国人,两边字符集编码不一样,尼玛显示都是乱码啊。为了统一,因而就发明了Unicode,将世界上全部的符号都归入其中,每个符号都给予一个独一无二的编码,如今Unicode能够容纳100多万个符号,每一个符号的编码都不同,这下可统一了,全部语言均可以互通,一个网页页面里能够同时显示各国文字code

五、然而,Unicode虽然统一了全世界字符的二进制编码,但没有规定如何存储啊,亲。x86和amd体系结构的电脑小端序和大端序都分不清,别提计算机如何识别究竟是Unicode仍是ASCII了。
若是Unicode统一规定,每一个符号用三个或四个字节表示,那么每一个英文字母前都必然有二到三个字节是0,文本文件的大小会所以大出二三倍,这对于存储来讲是极大的浪费。
这样致使一个后果:出现了Unicode的多种存储方式orm

六、互联网的兴起,网页上要显示各类字符,必须统一啊,亲。UTF-8就是Unicode最重要的实现方式之一。另外还有UTF-1六、UTF-32等。UTF-8不是固定字长编码的,而是一种变长的编码方式它可使用1~4个字节表示一个符号,根据不一样的符号而变化字节长度。这是种比较巧妙的设计,若是一个字节的第一位是0,则这个字节单独就是一个字符;若是第一位是1,则连续有多少个1,就表示当前字符占用多少个字节blog

七、注意Unicode的字符编码和UTF-8的存储编码表示是不一样的,例如"严"字的Unicode码是4E25,UTF-8编码是E4B8A5,这个7里面解释了的,UTF-8编码不只考虑了编码,还考虑了存储,E4B8A5是在存储识别编码的基础上塞进了4E25

八、UTF-8 使用一至四个字节为每一个字符编码。128 个 ASCII 字符(Unicode 范围由 U+0000 至 U+007F)只需一个字节,带有变音符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及马尔代夫语(Unicode 范围由 U+0080 至 U+07FF)须要二个字节,其余基本多文种平面(BMP)中的字符(CJK属于此类-Qieqie注)使用三个字节,其余 Unicode 辅助平面的字符使用四字节编码。

九、最后,常规来看,中文汉字在UTF-8中到底占几个字节,通常是3个字节,最多见的编码方式是1110xxxx 10xxxxxx

 

几种编码格式的简单介绍

  • ASCII 码

学过计算机的人都知道 ASCII 码,总共有 128 个,用一个字节的低 7 位表示,0~31 是控制字符如换行回车删除等;32~126 是打印字符,能够经过键盘输入而且可以显示出来。

  • ISO-8859-1

128 个字符显然是不够用的,因而 ISO 组织在 ASCII 码基础上又制定了一些列标准用来扩展 ASCII 编码,它们是 ISO-8859-1~ISO-8859-15,其中 ISO-8859-1 涵盖了大多数西欧语言字符,全部应用的最普遍。ISO-8859-1 仍然是单字节编码,它总共能表示 256 个字符。

  • GB2312

它的全称是《信息交换用汉字编码字符集 基本集》,它是双字节编码,总的编码范围是 A1-F7,其中从 A1-A9 是符号区,总共包含 682 个符号,从 B0-F7 是汉字区,包含 6763 个汉字。

  • GBK

全称叫《汉字内码扩展规范》,是国家技术监督局为 windows95 所制定的新的汉字内码规范,它的出现是为了扩展 GB2312,加入更多的汉字,它的编码范围是 8140~FEFE(去掉 XX7F)总共有 23940 个码位,它能表示 21003 个汉字,它的编码是和 GB2312 兼容的,也就是说用 GB2312 编码的汉字能够用 GBK 来解码,而且不会有乱码。

  • GB18030

全称是《信息交换用汉字编码字符集》,是我国的强制标准,它多是单字节、双字节或者四字节编码,它的编码与 GB2312 编码兼容,这个虽然是国家标准,可是实际应用系统中使用的并不普遍。

  • UTF-16

说到 UTF 必需要提到 Unicode(Universal Code 统一码),ISO 试图想建立一个全新的超语言字典,世界上全部的语言均可以经过这本字典来相互翻译。可想而知这个字典是多么的复杂,关于 Unicode 的详细规范能够参考相应文档。Unicode 是 Java 和 XML 的基础,下面详细介绍 Unicode 在计算机中的存储形式。

UTF-16 具体定义了 Unicode 字符在计算机中存取方法。UTF-16 用两个字节来表示 Unicode 转化格式,这个是定长的表示方法,不论什么字符均可以用两个字节表示,两个字节是 16 个 bit,因此叫 UTF-16。UTF-16 表示字符很是方便,每两个字节表示一个字符,这个在字符串操做时就大大简化了操做,这也是 Java 以 UTF-16 做为内存的字符存储格式的一个很重要的缘由。

  • UTF-8

UTF-16 统一采用两个字节表示一个字符,虽然在表示上很是简单方便,可是也有其缺点,有很大一部分字符用一个字节就能够表示的如今要两个字节表示,存储空间放大了一倍,在如今的网络带宽还很是有限的今天,这样会增大网络传输的流量,并且也不必。而 UTF-8 采用了一种变长技术,每一个编码区域有不一样的字码长度。不一样类型的字符能够是由 1~4 个字节组成。

UTF-8 有如下编码规则:
若是一个字节,最高位(第 8 位)为 0,表示这是一个 ASCII 字符(00 - 7F)。可见,全部 ASCII 编码已是 UTF-8 了。
若是一个字节,以 11 开头,连续的 1 的个数暗示这个字符的字节数,例如:110xxxxx 表明它是双字节 UTF-8 字符的首字节。
若是一个字节,以 10 开始,表示它不是首字节,须要向前查找才能获得当前字符的首字节

代码示例

public class CharacterDemo {

    public static void main(String [] args) {

        String chinese = "中";
        String english = "A";
        String cha = "0x20001";
        int c = 0x20001;
        CharacterDemo.characterTest(english);
        System.out.println("=============以上是英文字符输出信息=================");

        CharacterDemo.characterTest(chinese);
        System.out.println("=============以上是中文字符输出信息=================");

        CharacterDemo.characterTest(cha);
        System.out.println("==========================================");

        CharacterDemo.binaryTest(c);
        System.out.println("==========================================");
    }

    private static void characterTest(String str) {
        CharacterDemo.getLengthByEncodeing(str,"GB2312");
        CharacterDemo.getLengthByEncodeing(str,"GBK");
        CharacterDemo.getLengthByEncodeing(str,"GB2312");
        CharacterDemo.getLengthByEncodeing(str,"GB18030");
        CharacterDemo.getLengthByEncodeing(str,"ISO-8859-1");
        CharacterDemo.getLengthByEncodeing(str,"UTF-8");
        CharacterDemo.getLengthByEncodeing(str,"UTF-16");
        CharacterDemo.getLengthByEncodeing(str,"UTF-16BE");
        CharacterDemo.getLengthByEncodeing(str,"UTF-16LE");
    }

    private static void binaryTest(int c) {
        char[] arr = Character.toChars(c);
        String s = new String(arr);
        System.out.println("char array length:" + arr.length);
        System.out.println("content:|  " + s + " |");
        System.out.println("String length:" + s.length());

        CharacterDemo.getLengthByEncodeing(s, "GB2312");
        CharacterDemo.getLengthByEncodeing(s, "GBK");
        CharacterDemo.getLengthByEncodeing(s, "GB2312");
        CharacterDemo.getLengthByEncodeing(s, "GB18030");
        CharacterDemo.getLengthByEncodeing(s, "ISO-8859-1");
        CharacterDemo.getLengthByEncodeing(s, "UTF-8");
        CharacterDemo.getLengthByEncodeing(s, "UTF-16");
        CharacterDemo.getLengthByEncodeing(s, "UTF-16BE");
        CharacterDemo.getLengthByEncodeing(s, "UTF-16LE");
    }

    private static void getLengthByEncodeing(String str, String encodingName) {
        try {
            System.out.format("编码格式:%s\t\t", encodingName);
            System.out.format("字节长度:%s\n",str.getBytes(encodingName).length);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}
编码格式:GB2312        字节长度:1
编码格式:GBK           字节长度:1
编码格式:GB2312        字节长度:1
编码格式:GB18030       字节长度:1
编码格式:ISO-8859-1    字节长度:1
编码格式:UTF-8         字节长度:1
编码格式:UTF-16        字节长度:4
编码格式:UTF-16BE      字节长度:2
编码格式:UTF-16LE      字节长度:2
=============以上是英文字符输出信息=================
编码格式:GB2312        字节长度:2
编码格式:GBK           字节长度:2
编码格式:GB2312        字节长度:2
编码格式:GB18030       字节长度:2
编码格式:ISO-8859-1    字节长度:1
编码格式:UTF-8         字节长度:3
编码格式:UTF-16        字节长度:4
编码格式:UTF-16BE      字节长度:2
编码格式:UTF-16LE      字节长度:2
=============以上是中文字符输出信息=================
编码格式:GB2312        字节长度:7
编码格式:GBK           字节长度:7
编码格式:GB2312        字节长度:7
编码格式:GB18030       字节长度:7
编码格式:ISO-8859-1    字节长度:7
编码格式:UTF-8         字节长度:7
编码格式:UTF-16        字节长度:16
编码格式:UTF-16BE      字节长度:14
编码格式:UTF-16LE      字节长度:14
==========================================
char array length:2
content:|  𠀁 |
String length:2
编码格式:GB2312        字节长度:1
编码格式:GBK           字节长度:1
编码格式:GB2312        字节长度:1
编码格式:GB18030       字节长度:4
编码格式:ISO-8859-1    字节长度:1
编码格式:UTF-8         字节长度:4
编码格式:UTF-16        字节长度:6
编码格式:UTF-16BE      字节长度:4
编码格式:UTF-16LE      字节长度:4
==========================================
相关文章
相关标签/搜索