zoukankan      html  css  js  c++  java
  • Java中一个字符用unicode编码为什么不是两字节

    按照之前对Unicode及utf-8的描述,一个字符以Unicode编码应该是2个字节,英文字符用utf-8占一个字节,中文可能是3-4个字节。那么我们来看看这段代码的运行结果。

    import java.io.UnsupportedEncodingException;
    import java.math.BigInteger;
    /**
     * @author qiang.xie
     * @date 2017/9/7
     */
    
    public class Test {
        public static void main(String[] arg) throws Exception{
            String s1="a好";
            printBytesLen(s1,"gbk");
            printBytesLen(s1,"utf-8");
            printBytesLen(s1,"utf-16");
            printBytesLen(s1,"unicode");
            printBytesLen("h","utf-8");
            printBytesLen("h","unicode");
            printBytesLen("h","utf-16");
        }
            
        public static void printBytesLen(String string, String charset)
         throws UnsupportedEncodingException {
               byte[] bytes=string.getBytes(charset);
               System.out.println("["+string+"]使用["+charset+"]占用的字节长度:"+bytes.length+";十六进制:"+bytesToHex(bytes));
        }  
                 
        //转16进制
        public static String bytesToHex(byte[] bytes){
             return new BigInteger(1,bytes).toString(16);
        }
    }

    运行结果:

    [a好]使用[utf-8]占用的字节长度:4;十六进制:61e5a5bd
    [a好]使用[utf-16]占用的字节长度:6;十六进制:feff0061597d
    [a好]使用[unicode]占用的字节长度:6;十六进制:feff0061597d
    [h]使用[utf-8]占用的字节长度:1;十六进制:68
    [h]使用[unicode]占用的字节长度:4;十六进制:feff0068
    [h]使用[utf-16]占用的字节长度:4;十六进制:feff0068

    我猜你们又要凌乱了。

    为什么用unicode或utf-16总数要多出两个字节?且听我一一道来。

    二进制的高低位

    一个16位的二级制数符占两个字节的存储空间,即高位字节和低位字节。如果你是在纸上书写一个16位的数,你总是会把高位字节写在前面,而把低位字节写在后面。然而,当这个数被存储到计算机中时,并没有固定的存储顺序。

    如果我们用M和L分别表示高位字节和低位字节,那么可以有两种方式把这两个字节存储到计算机存中,即M在前L在后或者L在前M在后。

    把M存储在前的顺序被称为“正向(forward)”或“高位优先(big—endian)”顺序;把L存储在前的顺序被称为“逆向(reverse)”或“低位优先(little—endian)”顺序。

    big—endian这个术语的含义是数的“高位(big end)”存储在前。

    大多数计算机按正向顺序存储一个数,Intel CPU按逆向顺序存储一个数,因此,如果试图将基于Intel CPU的计算机连到其它类型的计算机上,就可能会引起混乱。另外,当字节流在网络上传输时,如果你从高位到低位的顺序发送,接受者却以低位到高位的顺序结束,也会发生混乱。

    那么,怎样明确的通过一些方式来表明字节的高低位顺序呢?

    BOM

    BOM(Byte Order Mark),字节顺序标记。

    unicode编码规范中编码中有一个叫做 "Zero Width No-Break Space" ,中文译名作“零宽无间断间隔”的字符,它的编码用十六进制表示是FEFF。而 FEFF 在 unicode 中是不存在的字符,所以不应该出现在实际内容中。unicode 规范建议我们在传输字节流前,先传输这个FEFF。这样如果接收者收到 FEFF,就表明这个字节流是Big-Endian(高位在前) 的;如果收到FFFE,就表明这个字节流是 Little- Endian(低位在前)的。因此字符 "Zero Width No-Break Space" (“零宽无间断间隔”)又被称作 BOM。

    说白了就是用一个专门的unicode字符来加在实际内容的前面,来告诉使用者我这个内容里的字节顺序是高位在前还是低位在前的。

    如此一来,上面程序的结果也就能解释的通了。

    基于unicode(utf-16)的编码总会比实际内容多出两个字节,就是那个BOM,它也是一个unicode字符,所有也需两字节。

    而utf-8编码有自己特殊的特征,它完全可以根据自己的编码方式避免这个高低位顺序的问题,所以不需要BOM。

    转载:https://mp.weixin.qq.com/s?timestamp=1510898006&src=3&ver=1&signature=SZlSxEWJYVinrj2MnVMDESmG2QNKElpjfJi0dW2v7FNUTVW8fikv2qxfIN8w10WiffqgevZnxVfxNpKgrni5jG5Hk28KXKjI--7lQHE*ac6EpWFtGJkYjzfxScB3F6yyrPilkbvCUJ4KruGSbajdwkMbhTE3BY1Q9yFcbhpahr0=

  • 相关阅读:
    stress-Linux系统压力测试工具使用及系统负载很高的几种场景测试
    execsnoop-短时进程追踪工具
    走迷宫--DFS
    马踏棋盘--dfs
    查询前缀出现的次数----字典树
    找两个质数和为偶数的两个数
    煤气灶---递归
    求合力
    hdu2089---不要62(数位DP)
    轻重匹配
  • 原文地址:https://www.cnblogs.com/taich-flute/p/7851234.html
Copyright © 2011-2022 走看看