操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    用過批處理腳本的小伙伴都會遇到中文亂碼這個問題,下面我們從產生原因來分析和解決亂碼問題。

    一、批處理亂碼的原因。

    一提到亂碼,我們首先想到的肯定是編碼的問題,沒錯,就是編碼的問題。

    說得更準確一點,就是在編寫批處理腳本時用的編碼和批處理腳本執行時候的編碼不一致導致的亂碼問題。

    1、批處理腳本由誰來運行?

    在Windows系統中,批處理腳本是由cmd.exe 。

    2、執行批處理腳本的命令行用的是什么編碼?

    cmd.exe應用程序采用ANSI編碼。

    3、什么是ANSI編碼?

    在Windows操作系統中,為了使計算機支持多種語言,例如簡體中文,繁體中文,日文, 韓文等等國家的語言文字,系統定義了一個叫做 ANSI 的字符代碼,這個字符代碼會根據操作系統設置的語言環境來執行對應的編碼標準,比如在簡體中文Windows操作系統中,ANSI 編碼代表 GB2312編碼;在繁體中文Windows操作系統中,ANSI編碼代表Big5;在日文Windows操作系統中,ANSI 編碼代表 JIS 編碼。

    4、編寫批處理腳本時用得是什么編碼?

    通常我們在編寫批處理腳本的時候是新建一個文本文檔,在文檔中編寫完命令以后,再更改文件的后綴為.bat。

    采用這種方式編寫的批處理腳本文件一般都是UTF-8編碼格式。第2和第4用到的編碼不一致,那肯定會出現亂碼的問題。

    二、批處理亂碼的解決方案。

    只需要將批處理腳本的編碼更改為 ANSI 編碼即可。

    注意:更改為 ANSI 編碼后,批處理腳本文件中的文字可能會變成亂碼,只需要把亂碼文字刪除重寫即可正常運行。

    字符集轉換概述

    我們有必要說明一下, 字符 其實是面向人類的一個概念,計算機可并不關心字符是什么,它只關心這個字符對應的字節編碼是什么。對于一個字節序列,計算機怎么知道它是使用什么字符集編碼的呢?計算機不知道,所以其實在計算機中表示一個字符串時,都需要附帶上它對應的字符集是什么,就像這樣(以C++語言為例):

    class String {
        byte* content;
        CHARSET_INFO* charset;
    }

    比方說我們現在有一個以 utf8 字符集編碼的漢字 '我' ,那么意味著計算機中不僅僅要存儲 '我' 的utf8編碼 0xE68891 ,還需要存儲它是使用什么字符集編碼的信息,就像這樣:

    {
        content: 0xE68891;
        charset: utf8;
    }

    計算機內部包含將一種字符集轉換成另一種字符集的函數庫,也就是某個字符在某種字符集下的編碼可以很順利的轉換為另一種字符集的編碼,我們將這個過程稱之為 字符集轉換 。比方說我們可以將上述采用utf8字符集編碼的字符'我',轉換成gbk字符集編碼的形式,就變成了這樣:

    {
        content: 0xCED2;
        charset: gbk;
    }

    小貼士:我們上邊所說的'編碼'可以當作動詞,也可以當作名詞來理解。當作動詞的話意味著將一個字符映射到一個字節序列的過程,當作名詞的話意味著一個字符對應的字節序列。大家根據上下文理解'編碼'的含義。

    MySQL客戶端和服務器是怎么通信的

    MySQL客戶端發送給服務器的請求以及服務器發送給客戶端的響應其實都是遵從一定格式的,我們把它們通信過程中事先規定好的數據格式稱之為MySQL通信協議,這個協議是公開的,我們可以簡單的使用wireshark等截包軟件十分方便的分析這個通信協議。在了解了這個通信協議之后,我們甚至可以動手制作自己的客戶端軟件。市面上的MySQL客戶端軟件多種多樣,我們并不想各個都分析一下,現在只選取在MySQL安裝目錄的 bin 目錄下自帶的 mysql 程序(此處的 mysql 程序指的是名字叫做 mysql 的一個可執行文件),如圖所示:

    我們在計算機的黑框框中執行該可執行文件,就相當于啟動了一個客戶端,就像這樣:

    小貼士:我們這里的'黑框框'指的是Windows操作系統中的cmd.exe或者UNIX系統中的Shell。

    我們通常是按照下述步驟使用MySQL的:

    1. 啟動客戶端并連接到服務器
    2. 客戶端發送請求。
    3. 服務器接收到請求
    4. 服務器處理請求
    5. 服務器處理請求完畢生成對該客戶端的響應
    6. 客戶端接收到響應

    下邊我們就詳細分析一下每個步驟中都影響到了哪些字符集。

    啟動客戶端并連接到服務器過程

    每個MySQL客戶端都維護者一個客戶端默認字符集,這個默認字符集按照下邊的套路進行取值:

    • 自動檢測操作系統使用的字符集MySQL客戶端會在啟動時檢測操作系統當前使用的字符集,并按照一定規則映射成為MySQL支持的一些字符集(通常是操作系統當前使用什么字符集,就映射為什么字符集,有一些特殊情況,比方說如果操作系統當前使用的是ascii字符集,會被映射為latin1字符集)。
      • 當我們使用UNIX操作系統時此時會調用操作系統提供的 nl_langinfo(CODESET) 函數來獲取操作系統當前正在使用的字符集,而這個函數的結果是依賴 LC_ALL 、 LC_CTYPE 、 LANG 這三個環境變量的。其中 LC_ALL 的優先級比 LC_CTYPE 高, LC_CTYPE 的優先級比 LANG 高。也就是說如果設置了 LC_ALL ,不論有沒有設置 LC_CTYPE 或者 LANG ,最終都以 LC_ALL 為準;如果沒有設置 LC_ALL ,那么就以 LC_CTYPE 為準;如果既沒有設置 LC_ALL 也沒有設置 LC_CTYPE ,就以 LANG 為準。比方說我們將環境變量 LC_ALL 設置為 zh_CN.UTF-8 ,就像這樣:export LC_ALL=zh_CN.UTF-8 那么我們在黑框框里啟動MySQL客戶端時,MySQL客戶端就會檢測到這個操作系統使用的是 utf8 字符集,并將客戶端默認字符集設置為 utf8 。當然,如果這三個環境變量都沒有設置,那么 nl_langinfo(CODESET) 函數將返回操作系統默認的字符集,比方說在我的 macOS 10.15.3 操作系統中,該默認字符集為:US-ASCII 此時MySQL客戶端的默認字符集將會被設置為 latin1 。另外,我們這里還需要強調一下,我們使用的黑框框展示字符的時候有一個自己特有的字符集,比如在我的mac上使用 iTerm2 作為黑框框,我們可以打開:Preferences->Profiles->Terminal選項卡,可以看到 iTerm2 使用 utf8 來展示字符:我們一般要把黑框框展示字符時采用的編碼和操作系統當前使用的編碼保持一致,如果不一致的話,我們敲擊的字符可能都無法顯示到屏幕上。比方說如果我此時把 LC_ALL 屬性設置成 GBK ,那么我們再向黑框框上輸入漢字的話,屏幕都不會顯示了,就像這樣(如下圖所示,我敲擊了漢字 '我' 的效果):
      • 當我們使用Windows操作系統時此時會調用操作系統提供的 GetConsoleCP 函數來獲取操作系統當前正在使用的字符集。在Windows里,會把當前cmd.exe使用的字符集映射到一個數字,稱之為代碼頁(英文名: code page ),我們可以通過右鍵點擊 cmd.exe 標題欄,然后點擊屬性->選項,如下圖所示, 當前代碼頁 的值是936,代表當前cmd.exe使用gbk字符集:更簡便一點,我們可以運行 chcp 命令直接看到當前code page是什么:這樣我們在黑框框里啟動MySQL客戶端時,MySQL客戶端就會檢測到這個操作系統使用的是 gbk 字符集,并將客戶端默認字符集設置為 gbk 。我們前邊提到的utf8字符集對應的代碼頁為 65001 ,如果當前代碼頁的值為65001,之后再啟動MySQL客戶端,那么客戶端的默認字符集就會變成 utf8 。
    • 如果MySQL不支持自動檢測到的操作系統當前正在使用的字符集,或者在某些情況下不允許自動檢測的話,MySQL會使用它自己的內建的默認字符集作為客戶端默認字符集。這個內建的默認字符集在 MySQL 5.7 以及之前的版本中是 latin1 ,在 MySQL 8.0 中修改為了 utf8mb4 。
    • 使用了 default-character-set 啟動參數如果我們在啟動MySQL客戶端是使用了 default-character-set 啟動參數,那么客戶端的默認字符集將不再檢測操作系統當前正在使用的字符集,而是直接使用啟動參數 default-character-set 所指定的值。比方說我們使用如下命令來啟動客戶端:mysql --default-character-set=utf8 那么不論我們使用什么操作系統,操作系統目前使用的字符集是什么,我們都將會以utf8作為MySQL客戶端的默認字符集。

    在確認了MySQL客戶端默認字符集之后,客戶端就會向服務器發起登陸請求,傳輸一些諸如用戶名、密碼等信息,在這個請求里就會包含客戶端使用的默認字符集是什么的信息,服務器收到后就明白了稍后客戶端即將發送過來的請求是采用什么字符集編碼的,自己生成的響應應該以什么字符集編碼了(劇透一下:其實服務器在明白了客戶端使用的默認字符集之后,就會將 character_set_client 、 character_set_connection 以及 character_set_result 這幾個系統變量均設置為該值)。

    客戶端發送請求

    登陸成功之后,我們就可以使用鍵盤在黑框框中鍵入我們想要輸入的MySQL語句,輸入完了之后就可以點擊回車鍵將該語句當作請求發送到服務器,可是客戶端發送的語句(本質是個字符串)到底是采用什么字符集編碼的呢?這其實涉及到應用程序和操作系統之間的交互,我們的MySQL客戶端程序其實是一個應用程序,它從黑框框中讀取數據其實是要調用操作系統提供的讀取接口。在不同的操作系統中,調用的讀取接口其實是不同的,我們還得分情況討論一下:

    • 對于UNIX操作系統來說在我們使用某個輸入法軟件向黑框框中輸入字符時,該字符采用的編碼字符集其實是操作系統當前使用的字符集。比方說當前 LC_ALL 環境變量的值為 zh_CN.UTF-8 ,那么意味著黑框框中的字符其實是使用utf8字符集進行編碼。稍后MySQL客戶端程序將調用操作系統提供的read函數從黑框框中讀取數據(其實就是所謂的從標準輸入流中讀取數據),所讀取的數據其實就是采用utf8字符集進行編碼的字節序列,稍后將該字節序列作為請求內容發送到服務器。這樣其實會產生一個問題,如果客戶端的默認字符集和操作系統當前正在使用的字符集不同,那么將產生比較尷尬的結果。比方說我們在啟動客戶端是攜帶了 --default-character-set=gbk 的啟動參數,那么客戶端的默認字符集將會被設置成gbk,而如果操作系統此時采用的字符集是utf8。比方說我們的語句中包含漢字 '我' ,那么客戶端調用 read 函數讀到的字節序列其實是 0xE68891 ,從而將 0xE68891 發送到服務器,而服務器認為客戶端發送過來的請求都是采用gbk進行編碼的,這樣就會產生問題(當然,這僅僅是發生亂碼問題的前奏,并不意味著產生亂碼,亂碼只有在最后一步,也就是客戶端應用程序將服務器返回的數據寫到黑框框里時才會發生)。
    • 對于Windows操作系統來說在Windows操作系統中,從黑框框中讀取數據調用的是Windows提供的 ReadConsoleW 函數。在該函數執行后,MySQL客戶端會得到一個寬字符數組(其實就是一組16位的UNICODE),然后客戶端需要把該寬字符數組再次轉換成客戶端使用的默認字符集編碼的字節序列,然后才將該字節序列作為請求的內容發送到服務器。這樣在UNIX操作系統中可能產生的問題,在Windows系統中卻可以避免。比方說我們在啟動客戶端是攜帶了 --default-character-set=gbk 的啟動參數,那么客戶端的默認字符集將會被設置成gbk,假如此時操作系統采用的字符集是utf8。比方說我們的語句中包含漢字 '我' ,那么客戶端調用 ReadConsoleW 函數先讀到一個代表著 我 字的寬字符數組,之后又將其轉換為客戶端的默認字符集,也就是gbk字符集編碼的數據 0xCED2 ,然后將 0xCED2 發送到服務器。此時服務器也認為客戶端發送過來的請求就是采用gbk進行編碼的,這樣就完全正確了~

    服務器接收請求

    服務器接收到到的請求本質上就是一個字節序列,服務器將其看作是采用系統變量 character_set_client 代表的字符集進行編碼的字節序列。 character_set_client 是一個SESSION級別的系統變量,也就是說每個客戶端和服務器建立連接后,服務器都會為該客戶端維護一個單獨的 character_set_client 變量,每個客戶端在登錄服務器的時候都會將客戶端的默認字符集通知給服務器,然后服務器設置該客戶端專屬的 character_set_client 。

    我們可以使用SET命令單獨修改 character_set_client 對應的值,就像這樣:

    SET character_set_client=gbk;
    

    需要注意的是, character_set_client 對應的字符集一定要包含請求中的字符,比方說我們把 character_set_client 設置成 ascii ,而請求中發送了一個漢字 '我' ,將會發生這樣的事情:

    mysql> SET character_set_client=ascii;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SHOW VARIABLES LIKE 'character%';
    +--------------------------+------------------------------------------------------+
    | Variable_name            | Value                                                |
    +--------------------------+------------------------------------------------------+
    | character_set_client     | ascii                                                |
    | character_set_connection | utf8                                                 |
    | character_set_database   | utf8                                                 |
    | character_set_filesystem | binary                                               |
    | character_set_results    | utf8                                                 |
    | character_set_server     | utf8                                                 |
    | character_set_system     | utf8                                                 |
    | character_sets_dir       | /usr/local/Cellar/mysql/5.7.21/share/mysql/charsets/ |
    +--------------------------+------------------------------------------------------+
    8 rows in set (0.00 sec)
    
    mysql> SELECT '我';
    +-----+
    | ??? |
    +-----+
    | ??? |
    +-----+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 1300
    Message: Invalid ascii character string: '\xE6\x88\x91'
    1 row in set (0.00 sec)

    如圖所示,最后提示了 'E6、88、91' 并不是正確的ascii字符。

    小貼士:可以將character_set_client設置為latin1,看看還會不會報告WARNINGS,以及為什么~

    服務器處理請求

    服務器在處理請求時會將請求中的字符再次轉換為一種特定的字符集,該字符集由系統變量 character_set_connection 表示,該系統變量也是SESSION級別的。每個客戶端在登錄服務器的時候都會將客戶端的默認字符集通知給服務器,然后服務器設置該客戶端專屬的 character_set_connection 。

    不過我們之后可以通過SET命令單獨修改這個 character_set_connection 系統變量。比方說客戶端發送給服務器的請求中包含字節序列 0xE68891 ,然后服務器針對該客戶端的系統變量 character_set_client 為 utf8 ,那么此時服務器就知道該字節序列其實是代表漢字 '我' ,如果此時服務器針對該客戶端的系統變量 character_set_connection 為gbk,那么在計算機內部還需要將該字符轉換為采用gbk字符集編碼的形式,也就是 0xCED2 。

    有同學可能會想這一步有點兒像脫了褲子放屁的意思,但是大家請考慮下邊這個查詢語句:

    mysql> SELECT 'a'='A';
    

    請問大家這個查詢語句的返回結果應該是TRUE還是FALSE?其實結果是不確定。這是因為我們并不知道比較兩個字符串的大小到底比的是什么!我們應該從兩個方面考慮:

    • 考慮一:這些字符串是采用什么字符集進行編碼的呢?
    • 考慮二:在我們確定了編碼這些字符串的字符集之后,也就意味著每個字符串都會映射到一個字節序列,那么我們怎么比較這些字節序列呢,是直接比較它們二進制的大小,還是有別的什么比較方式?比方說 'a' 和 'A' 在utf8字符集下的編碼分別為 0x61 和 0x41 ,那么 'a'='A' 是應該直接比較 0x61 和 0x41 的大小呢,還是將 0x61 減去32之后再比較大小呢?其實這兩種比較方式都可以,每一種比較方式我們都稱作一種 比較規則 (英文名: collation )。

    MySQL 中支持若干種字符集,我們可以使用 SHOW CHARSET 命令查看,如下圖所示(太多了,只展示幾種,具體自己運行一下該命令):

    mysql> SHOW CHARSET;
    +----------+---------------------------------+---------------------+--------+
    | Charset  | Description                     | Default collation   | Maxlen |
    +----------+---------------------------------+---------------------+--------+
    | big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
    | latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
    | latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
    | ascii    | US ASCII                        | ascii_general_ci    |      1 |
    | gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |
    | gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |
    | utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
    | utf8mb4  | UTF-8 Unicode                   | utf8mb4_general_ci  |      4 |
    | utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
    | utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
    | utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
    | binary   | Binary pseudo charset           | binary              |      1 |
    | gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
    +----------+---------------------------------+---------------------+--------+
    41 rows in set (0.04 sec)

    其中每一種字符集又對應著若干種比較規則,我們以utf8字符集為例(太多了,也只展示幾個):

    mysql> SHOW COLLATION WHERE Charset='utf8';
    +--------------------------+---------+-----+---------+----------+---------+
    | Collation                | Charset | Id  | Default | Compiled | Sortlen |
    +--------------------------+---------+-----+---------+----------+---------+
    | utf8_general_ci          | utf8    |  33 | Yes     | Yes      |       1 |
    | utf8_bin                 | utf8    |  83 |         | Yes      |       1 |
    | utf8_unicode_ci          | utf8    | 192 |         | Yes      |       8 |
    | utf8_icelandic_ci        | utf8    | 193 |         | Yes      |       8 |
    | utf8_latvian_ci          | utf8    | 194 |         | Yes      |       8 |
    | utf8_romanian_ci         | utf8    | 195 |         | Yes      |       8 |
    +--------------------------+---------+-----+---------+----------+---------+
    27 rows in set (0.00 sec)

    其中 utf8_general_ci 是utf8字符集默認的比較規則,在這種比較規則下是不區分大小寫的,不過 utf8_bin 這種比較規則就是區分大小寫的。

    在我們將請求中的字節序列轉換為 character_set_connection 對應的字符集編碼的字節序列后,也要配套一個對應的比較規則,這個比較規則就由 collation_connection 系統變量來指定。我們現在通過SET命令來修改一下和 collation_connection 的值分別設置為 utf8 和 utf8_general_ci ,然后比較一下 'a' 和 'A' :

    mysql> SET character_set_connection=utf8;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SET collation_connection=utf8_general_ci;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT 'a'='A';
    +-----------+
    | 'a'='A' |
    +-----------+
    |         1 |
    +-----------+
    1 row in set (0.00 sec)

    可以看到在這種情況下這兩個字符串就是相等的。

    我們現在通過SET命令來修改一下和 collation_connection 的值分別設置為 utf8 和 utf8_bin ,然后比較一下 'a' 和 'A' :

    mysql> SET character_set_connection=utf8;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SET collation_connection=utf8_bin;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT 'a'='A';
    +-----------+
    | 'a'='A' |
    +-----------+
    |         0 |
    +-----------+
    1 row in set (0.00 sec)

    可以看到在這種情況下這兩個字符串就是不相等的。

    當然,如果我們并不需要單獨指定將請求中的字符串采用何種字符集以及比較規則的話,并不用太關心 character_set_connection 和 collation_connection 設置成啥,不過需要注意一點,就是 character_set_connection 對應的字符集必須包含請求中的字符。

    服務器處理請求完畢生成對該客戶端的響應

    為了故事的順利發展,我們先創建一個表:

    CREATE TABLE t (
        c VARCHAR(100)
    ) ENGINE=INNODB CHARSET=utf8;

    然后向這個表插入一條記錄:

    INSERT INTO t VALUE('我');

    現在這個表中的數據就如下所示:

    mysql> SELECT * FROM t;
    +------+
    | c    |
    +------+
    | 我   |
    +------+
    1 row in set (0.00 sec)

    我們可以看到該表中的字段其實是使用 utf8 字符集編碼的,所以底層存放格式是: 0xE68891 ,將它讀出后需要發送到客戶端,是不是直接將 0xE68891 發送到客戶端呢?這可不一定,這個取決于 character_set_result 系統變量的值,該系統變量也是一個SESSION級別的變量。服務器會將該響應轉換為 character_set_result 系統變量對應的字符集編碼后的字節序列發送給客戶端。每個客戶端在登錄服務器的時候都會將客戶端的默認字符集通知給服務器,然后服務器設置該客戶端專屬的 character_set_result 。

    我們也可以使用SET命令來設置 character_set_result 的值。不過也需要注意, character_set_result 對應的字符集應該包含響應中的字符。

    這里再強調一遍, character_set_client 、 character_set_connection 和 character_set_result 這三個系統變量是服務器的系統變量,每個客戶端在與服務器建立連接后,服務器都會為這個連接維護這三個變量,如圖所示(我們假設連接1的這三個變量均為 utf8 ,連接1的這三個變量均為 gbk ,連接1的這三個變量均為 ascii ,):

    一般情況下 character_set_client 、 character_set_connection 和 character_set_result 這三個系統變量應該和客戶端的默認字符集相同, SET names 命令可以一次性修改這三個系統變量:

    SET NAMES 'charset_name'
    

    該語句和下邊三個語句等效:

    SET character_set_client=charset_name;
    SET character_set_results=charset_name;
    SET character_set_connection=charset_name;

    不過這里需要大家特別注意, SET names 語句并不會改變客戶端的默認字符集!

    客戶端接收到響應

    客戶端收到的響應其實仍然是一個字節序列。客戶端是如何將這個字節序列寫到黑框框中的呢,這又涉及到應用程序和操作系統之間的一次交互。

    • 對于UNIX操作系統來說,MySQL客戶端向黑框框中寫入數據使用的是操作系統提供的 fputs 、 putc 或者 fwrite 函數,這些函數基本上相當于直接就把接收到的字節序列寫到了黑框框中(請注意我們用詞: '基本上相當于' ,其實內部還會做一些工作,但是我們這里就不想再關注這些細節了)。此時如果該字節序列實際的字符集和黑框框展示字符所使用的字符集不一致的話,就會發生所謂的亂碼(大家注意,這個時候和操作系統當前使用的字符集沒啥關系)。比方說我們在啟動MySQL客戶端的時候使用了 --default-character-set=gbk 的啟動參數,那么服務器的 character_set_result 變量就是gbk。然后再執行 SELECT * FROM t 語句,那么服務器就會將字符 '我' 的gbk編碼,也就是 0xCDE2 發送到客戶端,客戶端直接把這個字節序列寫到黑框框中,如果黑框框此時采用utf8字符集展示字符,那自然就會發生亂碼。
    • 對于Windows操作系統來說,MySQL客戶端向黑框框中寫入數據使用的是操作系統提供的 WriteConsoleW 函數,該函數接收一個寬字符數組,所以MySQL客戶端調用它的時候需要顯式地將它從服務器收到的字節序列按照客戶端默認的字符集轉換成一個寬字符數組。正因為這一步驟的存在,所以可以避免上邊提到的一個問題。比方說我們在啟動MySQL客戶端的時候使用了 --default-character-set=gbk 的啟動參數,那么服務器的 character_set_result 變量就是gbk。然后再執行 SELECT * FROM t 語句,那么服務器就會將字符 '我' 的gbk編碼,也就是 0xCDE2 發送到客戶端,客戶端將這個字節序列先從客戶端默認字符集,也就是gbk的編碼轉換成一個寬字符數組,然后再調用 WriteConsoleW 函數寫到黑框框,黑框框自然可以把它顯示出來。

    亂碼問題應該如何分析

    好了,介紹了各個步驟中涉及到的各種字符集,大家估計也看的眼花繚亂了,下邊總結一下我們遇到亂碼的時候應該如何分析,而不是胡子眉毛一把抓,隨便百度一篇文章,然后修改某個參數,運氣好修改了之后改對了,運氣不好改了一天也改不好。知其然也要知其所以然,在學習了本篇文章后,大家一定要有節奏的去分析亂碼問題:

    • 我使用的是什么操作系統
      • 對于UNIX系統用戶來說,要搞清楚我使用的黑框框到底是使用什么字符集展示字符,就像是 iTerm2 中的 character encoding 屬性:同樣還要搞清楚操作系統當前使用什么字符集,運行 locale 命令查看:王大爺喊你輸入呢,跟這兒>locale LANG="" LC_COLLATE="zh_CN.UTF-8" LC_CTYPE="zh_CN.UTF-8" LC_MESSAGES="zh_CN.UTF-8" LC_MONETARY="zh_CN.UTF-8" LC_NUMERIC="zh_CN.UTF-8" LC_TIME="zh_CN.UTF-8" LC_ALL="zh_CN.UTF-8" 王大爺喊你輸入呢,跟這兒>沒有什么特別極端的特殊需求的話,一定要保證上述兩個字符集是相同的,否則可能連漢字都輸入不進去!
      • 對于Windows用戶來說搞清楚自己使用的黑框框的代碼頁是什么,也就是操作系統當前使用的字符集是什么。
    • 搞清楚客戶端的默認字符集是什么啟動MySQL客戶端的時候有沒有攜帶 --default-character-set 參數,如果攜帶了,那么客戶端默認字符集就以該參數指定的值為準。否則分析自己操作系統當前使用的字符集是什么。
    • 搞清楚客戶端發送請求時是以什么字符集編碼請求的
      • 對于UNIX系統來說,我們可以認為請求就是采用操作系統當前使用的字符集進行編碼的。
      • 對于Windows系統來說,我們可以認為請求就是采用客戶端默認字符集進行編碼的。
    • 通過執行 SHOW VARIABLES LIKE 'character%' 命令搞清楚:
      • character_set_client :服務器是怎樣認為客戶端發送過來的請求是采用何種字符集編碼的
      • character_set_connection :服務器在運行過程中會采用何種字符集編碼請求中的字符
      • character_set_result :服務器會將響應使用何種字符集編碼后再發送給客戶端的
    • 客戶端收到響應之后:對于服務器發送過來的字節序列來說:
      • 在UNIX操作系統上,可以認為會把該字節序列直接寫到黑框框里。此時應該搞清楚我們的黑框框到底是采用何種字符集展示數據。
      • 在Windows操作系統上,該字節序列會被認為是由客戶端字符集編碼的數據,然后再轉換成寬字符數組寫入到黑框框中。
網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有