中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

細說 Java 中的字符和字符串( 二 )

2018-07-20    來源:importnew

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

我們上次在《細說Java中的字符和字符串(一)》說了Java中char和中文字符之間的關系,說明了char能不能存儲一個中文字符,以及如何判斷Java的字符串是否包含中文字符。
這次再看一下MySQL數據庫中VARCHAR(N)中的N表示什么,什么會限制N的大小。然后,從Java的String源代碼分析一下中文字符在Java字符串里是如何存儲的。

VARCHAR(N)中的N代表什么?

和第一篇類似,我們依舊從官方文檔尋找最有權威的答案。我們從這里可以找到VARCHAR(N)中N代表什么的答案:https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html

由于原文比較長,這里先把關鍵片段貼一下:

答案就在這段文字里,我們翻譯一下原文:VARCHAR 或者VARBINARY類型的列最大可存儲的字節(jié)數不能超過一行的最大可存儲字節(jié)數,也就是65535字節(jié)。如果VARCHAR類型的列存儲的是多字節(jié)類型的字符,那么可存儲的最大字符數相對就會變少。比如:utf8mb4類型的字符一個字符最大可以占到4個字節(jié),所以一個VARCHAR類型的字段最多可以存儲16383個字符(65535/4)。

重點看比如的文字,可以看出來MySQL的VARCHAR(N)中的N代表的是多少個字符(Character),而Character的對于不同的編碼又代表什么呢?

一起看一下另一篇MySQL官網文檔的內容:https://dev.mysql.com/doc/refman/8.0/en/charset-unicode.html

VARCHAR(N)的N值不論是哪種編碼,都對應到了字符級別,也就是這個列可以存下N個字符。MySQL的utf8和Java里的utf8不一樣,MySQL的實現里utf8最大只允許存儲3個字節(jié)。從上一篇我們知道,utf8編碼最長有4個字節(jié),那么4個字節(jié)的utf8字符MySQL的utf8類型是存不下的。

所以,當需要存儲emoji表情符的時候,我們需要用utf8mb4類型的字符集才能存下。MySQL的utf8mb4字符集才能包含全部utf8字符,而MySQL的utf8字符集是一個不完全版本的utf8字符集。

總結一下:MySQL中VARCHAR(N)字段類型里邊的N代表最大可以存多少個字。如果選的是中文編碼,比如utf8編碼,那么N代表最大可以存多少個漢字。

VARCHAR(N)中的N可以是多大?

N的最大值主要限制因素是MySQL的最大行大小,原文地址在:https://dev.mysql.com/doc/refman/8.0/en/column-count-limit.html。

MySQL的行大小最大不能超過65535bytes,是說MySQL的一行里所有列占用字節(jié)數的和不能超過65535bytes。BLOB和TEXT比較特別,他們只占用9個字節(jié)大小,真實數據存儲在行外。

MySQL的uft8類型最多占3個字節(jié),MySQL允許的最大字符數是21844(65535/3-1),utf8mb4最多占4個字節(jié),所以允許的最大字符數是16382(65535/4-1)。這個數字有一點點偏差,因為VARCHAR類型需要1到2個字節(jié)存儲length,所以最大字符數可以按照減1計算。

從Java String分析Java的char和中文的關系

String有三類構造函數,一類是傳入byte[],一類是傳入char[],一類是傳入int[],如下:

public String(byte bytes[], int offset, int length);//字節(jié)流,轉成字符串
public String(char value[], int offset, int count);//字符流,轉成字符串。較少用,一般用在雙字節(jié)編碼的字節(jié)串轉String。
public String(int[] codePoints, int offset, int count);//代碼點,轉成字符串

String內部數據存儲使用的是char[]存儲,byte 是8字節(jié),char是16字節(jié),int是32字節(jié)。所以byte[]參數的構造函數會把byte[]解析成正確的代碼點,也就是int類型,再轉換成char[]類型存到String內部。

所以,我們這里只分析int[]類型入參的構造函數,來看一下String是如何把int類型的代碼點轉成char[]存起來的。從這里,也能看出來一個2個字節(jié)的Unicode和一個2個以上字節(jié)的Unicode代碼點是怎么存到String里的。

    public String(int[] codePoints, int offset, int count) {
        //....
        // Pass 1: 計算int[]轉成char[]后的長度
        int n = count;
        for (int i = offset; i < end; i++) {
            int c = codePoints[i];
            if (Character.isBmpCodePoint(c))//如果是BMP范圍的代碼點,那么計數加1
                continue;
            else if (Character.isValidCodePoint(c))//如果是超出BMP范圍的有效代碼點,那么計數加2
                n++;
            else throw new IllegalArgumentException(Integer.toString(c));
        }

        // Pass 2: 使用int[]的值填充char[]
        final char[] v = new char[n];

        for (int i = offset, j = 0; i < end; i++, j++) {
            int c = codePoints[i];
            if (Character.isBmpCodePoint(c))//如果是BMP范圍的代碼點,直接加入char[]
                v[j] = (char)c;
            else//如果是超出BMP范圍的有效代碼點,那么轉成2個char,存入char[]
                Character.toSurrogates(c, v, j++);
        }

        this.value = v;
    }

標簽: idc Mysql 代碼 數據庫

版權申明:本站文章部分自網絡,如有侵權,請聯系:west999com@outlook.com
特別注意:本站所有轉載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權歸原作者所有,如需使用,請與原作者聯系。

上一篇:談談微信支付曝出的漏洞

下一篇:CodeReview常見代碼問題