UTF-8(Unicode Transformation Format)

UTF-8(Unicode Transformation Format)_第1张图片

文章目录

  • 一、Unicode
    • 示例代码:
  • 二、网络传输与Unicode
  • 三、UTF-8如何编码
  • 四、使用UTF-8转换传输Unicode
  • 五、利用Java-API进行UTF8编码和解码
  • 六、利用代码输出Unicode编码和UTF8编码
  • 七、手写UTF8编码、解码
  • 八、总结UTF8

一、Unicode

UTF-8(Unicode Transformation Format)_第2张图片
UTF-8(Unicode Transformation Format)_第3张图片
UTF-8(Unicode Transformation Format)_第4张图片

示例代码:

package demo;

/**
 * @Date: 2023-3-17 周五 15:48
 * @Author: Special Care
 * @Description: TODO Unicode编码
 * @Version: 1.0.0
 */
public class UnicodeDemo01 {
    public static void main(String[] args) {
        /**
         * Unicode编码
         * Java中的字符存储的是一个符号的Unicode编码
         * 可以显示为10进制或16进制形式
         * Java的字符范围0~65535(FFFF)
         */
        char c1 = 'A'; // 65   41
        char c2 = '中'; // 20013   4e2d
        char c3 = '✈'; // 9992   2708
        char c4 = 'a'; // 97   61
        System.out.println((int)c1);// 65
        System.out.println(Integer.toHexString(c1));// 41
        System.out.println((int)c2);// 20013
        System.out.println(Integer.toHexString(c2));// 4e2d
        System.out.println((int)c3);// 9992
        System.out.println(Integer.toHexString(c3));// 2708
        System.out.println((int)c4);// 97
        System.out.println(Integer.toHexString(c4));// 61
    }
}

二、网络传输与Unicode

UTF-8(Unicode Transformation Format)_第5张图片
UTF-8(Unicode Transformation Format)_第6张图片
UTF-8(Unicode Transformation Format)_第7张图片
UTF-8(Unicode Transformation Format)_第8张图片
UTF-8(Unicode Transformation Format)_第9张图片
UTF-8(Unicode Transformation Format)_第10张图片

三、UTF-8如何编码

UTF-8(Unicode Transformation Format)_第11张图片
UTF-8(Unicode Transformation Format)_第12张图片

四、使用UTF-8转换传输Unicode

UTF-8(Unicode Transformation Format)_第13张图片
UTF-8(Unicode Transformation Format)_第14张图片
UTF-8(Unicode Transformation Format)_第15张图片
UTF-8(Unicode Transformation Format)_第16张图片
UTF-8(Unicode Transformation Format)_第17张图片
UTF-8(Unicode Transformation Format)_第18张图片
UTF-8(Unicode Transformation Format)_第19张图片
UTF-8(Unicode Transformation Format)_第20张图片
UTF-8(Unicode Transformation Format)_第21张图片
UTF-8(Unicode Transformation Format)_第22张图片
UTF-8(Unicode Transformation Format)_第23张图片
UTF-8(Unicode Transformation Format)_第24张图片
UTF-8(Unicode Transformation Format)_第25张图片
UTF-8(Unicode Transformation Format)_第26张图片
UTF-8(Unicode Transformation Format)_第27张图片

五、利用Java-API进行UTF8编码和解码

package demo;

import java.nio.charset.StandardCharsets;

/**
 * @Date: 2023-3-17 周五 16:44
 * @Author: Special Care
 * @Description: TODO 测试UTF-8编解码API
 * @Version: 1.0.0
 */
public class UTF8Demo {
    public static void main(String[] args) throws Exception{
        /**
         * 测试UTF-8编解码API
         */
        String str = "Javaλ表达式";
        // 将字符串中的文字进行UTF-8编码
        // str.getBytes(StandardCharsets.UTF_8)也可以写成str.getBytes("UTF_8")
        // 经过getBytes方法的转换得到了UTF-8编码的字节数组
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        // bytes就可以利用网络进行传输

        // 将字节数组中的UTF-8编码的字符进行解码
        // new String(bytes, "UTF-8")
        String s = new String(bytes, StandardCharsets.UTF_8);
        System.out.println(s); // Javaλ表达式
    }
}

六、利用代码输出Unicode编码和UTF8编码

package demo;

import java.nio.charset.StandardCharsets;

/**
 * @Date: 2023-3-17 周五 16:44
 * @Author: 李林泼
 * @Description: TODO 测试UTF-8编解码API
 * @Version: 1.0.0
 */
public class UTF8Demo {
    public static void main(String[] args) throws Exception{
        /**
         * 测试UTF-8编解码API
         */
        String str = "Javaλ表达式";
        // 将字符串中的文字进行UTF-8编码
        // str.getBytes(StandardCharsets.UTF_8)也可以写成str.getBytes("UTF_8")
        // 经过getBytes方法的转换得到了UTF-8编码的字节数组
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        // bytes就可以利用网络进行传输

        // 将字节数组中的UTF-8编码的字符进行解码
        // new String(bytes, "UTF-8")
        String s = new String(bytes, StandardCharsets.UTF_8);
        System.out.println(s);

        /**
         * 输出字符串中每个字符的Unicode
         * String str = "Javaλ表达式";
         */
        System.out.println("Unicode:");
        for (int i = 0; i < str.length(); i++) {
            // i = 0, 1, 2, 3, 4, ...
            char c = str.charAt(i);
            System.out.print(c);
            System.out.print(":");
            System.out.println(Integer.toBinaryString(c));
        }
        System.out.println();
        System.out.println("UTF-8:");
        for (byte b : bytes) {
            System.out.println(Integer.toBinaryString(b & 0xff));
        }

        /**
         * Javaλ表达式
         * Unicode:
         * J:1001010
         * a:1100001
         * v:1110110
         * a:1100001
         * λ:1110111011
         * 表:1000100001101000
         * 达:1000111110111110
         * 式:101111100001111
         *
         * UTF-8:
         * 1001010
         * 1100001
         * 1110110
         * 1100001
         * 11001110
         * 10111011
         * 11101000
         * 10100001
         * 10101000
         * 11101000
         * 10111110
         * 10111110
         * 11100101
         * 10111100
         * 10001111
         */
    }
}

七、手写UTF8编码、解码

package demo;

import java.util.Arrays;

/**
 * @Date: 2023-3-17 周五 17:15
 * @Author: 李林泼
 * @Description: TODO 手工编写UTF-8编码、解码
 * @Version: 1.0.0
 */
public class UTF8Coding {
    /**
     * 手工编写UTF-8编码
     * Char. number range  |    UTF-8 octet sequence
     *    (hexadecimal)    |           (binary)
     * --------------------+------------------------------
     * 0000 0000-0000 007F | 0xxxxxxx
     * 0000 0000-0000 07FF | 110xxxxx 10xxxxxx
     * 0000 0000-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
     * 0000 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
     */
    /**
     * 将一个字符串编码为UTF-8字节数组
     * @param str 被编码的字符串
     * @return 经过UTF-8编码以后字节数组
     */
     public static byte[] getBytes(String str){
         // 预估一下返回值的最大情况
         byte[] bytes = new byte[str.length() * 4];
         // index代表bytes数组中数据的存储位置
         int index = 0;
         // 遍历字符串中每个字符,根据字符的Unicode编码范围,进行编码
         // 将编码存储到bytes,bytes中就是返回值UTF-8数据
         for (int i = 0; i < str.length(); i++) {
             char c = str.charAt(i);
             // 判断c范围,根据范围进行编码
             if (c <= 0x7F){
                 // c在0~0x7F范围内,是1字节编码,1字节编码添加到bytes
                 bytes[index++] = (byte) c;
             }else if (c <= 0x7FF){
                 // c在0x80~0x7FF范围内,处理两个字节的UTF-8编码
                 //    b1       b2
                 // 110xxxxx 10xxxxxx
                 // 截取字符的后6位
                 //            0b111111
                 int b2 = (c & 0x3F) | 0b10000000;
                 //                    0b11111
                 int b1 = ((c >>> 6) & 0x1F) | 0b11000000;
                 bytes[index++] = (byte) b1;
                 bytes[index++] = (byte) b2;
             }else if (c < 0xFFFF){
                 // 处理3字节编码
                 // 1110xxxx 10xxxxxx 10xxxxxx
                 int b3 = (c & 0b111111) | 0b10000000;
                 int b2 = ((c >>> 6) & 0b111111) | 0b10000000;
                 int b1 = ((c >>> 12) & 0b1111) | 0b11100000;
                 bytes[index++] = (byte) b1;
                 bytes[index++] = (byte) b2;
                 bytes[index++] = (byte) b3;
             }
         }
         return Arrays.copyOf(bytes,index);
     }

    /**
     * 将UTF-8编码的字节数组解码为字符串(Unicode字符)
     * @param bytes UTF-8编码的字节
     * @return 解码以后的字符串
     */
     public static String decode(byte[] bytes){
         char[] chs = new char[bytes.length];
         int index = 0;
         // 遍历字节数组,检查每个字节
         // 如果字节以0开头,则是单字节编码
         // 如果是以110开头,则是双字节编码
         // 如果是以1110开头,则是三字节编码
         for (int i = 0; i < bytes.length; ) {
             int b1 = bytes[i++] & 0xff;
             if ((b1 >>> 7) == 0){
                 // 检查01001010是否为单字节编码0xxxxxxx
                 // b1      00000000 00000000 00000000 01001010
                 // b1>>>7  000000000000000 00000000 00000000 0
                 chs[index++] = (char)b1;
             }else if ((b1 >>> 5) == 0b110){
                 // 检查是否为双字节编码 b1 11001110 b2 10111011
                 // b1 -> int
                 // b1      00000000 00000000 00000000 11001110
                 // b1>>>5  0000000000000 00000000 00000000 110
                 int b2 = bytes[i++] & 0xff;
                 // b1      00000000 00000000 00000000 11001110
                 // b2      00000000 00000000 00000000 10111011
                 // c       00000000 00000000 0000001110 111011
                 int c = ((b1 & 0b11111)<<6) | (b2 & 0b111111);
                 chs[index++] = (char) c;
             }else if ((b1 >>> 4) == 0b1110){
                 // 检查是否为三字节编码:11101000 10100001 10101000
                 int b2 = bytes[i++] & 0xff;
                 int b3 = bytes[i++] & 0xff;
                 int c = ((b1 & 0b1111)<<12) | ((b2 & 0b111111)<<6) | (b3 & 0b111111);
                 System.out.println("b1:" + Integer.toBinaryString(b1));
                 System.out.println("b2:" + Integer.toBinaryString(b2));
                 System.out.println("b3:" + Integer.toBinaryString(b3));
                 System.out.println("c:" + Integer.toBinaryString(c));
                 chs[index++] = (char) c;
             }
         }
         return new String(chs,0,index);
     }

    public static void main(String[] args) {
        String str = "Javaλ表达式";
        System.out.println("Unicode:");
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            System.out.print(c);
            System.out.print(":");
            System.out.println(Integer.toBinaryString(c));
        }
        // 调用手写UTF-8编码方法
        byte[] bytes = getBytes(str);
        for (byte b : bytes) {
            System.out.println(Integer.toBinaryString(b & 0xff));
        }

        // 检查手写的UTF-8解码运算
        String s = decode(bytes);
        System.out.println(s);
    }

    /**
     * Unicode:
     * J:1001010
     * a:1100001
     * v:1110110
     * a:1100001
     * λ:1110111011
     * 表:1000100001101000
     * 达:1000111110111110
     * 式:101111100001111
     * 1001010
     * 1100001
     * 1110110
     * 1100001
     * 11001110
     * 10111011
     * 11101000
     * 10100001
     * 10101000
     * 11101000
     * 10111110
     * 10111110
     * 11100101
     * 10111100
     * 10001111
     * b1:11101000
     * b2:10100001
     * b3:10101000
     * c:1000100001101000
     * b1:11101000
     * b2:10111110
     * b3:10111110
     * c:1000111110111110
     * b1:11100101
     * b2:10111100
     * b3:10001111
     * c:101111100001111
     * Javaλ表达式
     */
}

八、总结UTF8

UTF-8(Unicode Transformation Format)_第28张图片
UTF-8(Unicode Transformation Format)_第29张图片

你可能感兴趣的:(Java,SE,java)