c#+mysql 中文亂碼

c#+mysql 中文亂碼

遇到一個奇怪的問題,C#讀取mysql中文正常,寫入時發生亂碼mysql

網上查閱緣由,發現以下信息web

---------------------------------------------------------------------sql

1、錯誤讀出

現象:一個已經存在數據的MySQL數據庫,該數據庫的數據用系統中其它軟件、網頁查看均正常,使用MySQLcc之類的客戶端查看也正常,但是在新寫的網頁中老是顯示亂碼。

分析:其它系統均可以正常查看數據,說明數據自己是沒有問題的。在網頁中顯示亂碼,必定是網頁的編碼字符集和獲取到的數據的編碼字符集不一至。好比數據庫的字符集是UTF8的,而網頁的字符集是gb2312的,那麼網頁就會把UTF8編碼的字體串看成gb2312的來處理,結果產生亂碼。

解決辦法:在鏈接數據庫時,設定鏈接字符集,使鏈接字符集和當前網頁或客戶端程序使用的字符集一致。可使用MySQL的Set Names指令設定鏈接字符集。假設網頁的字體集爲gb2312。在鏈接MySQL後,在鏈接上執行以下SQL語句:

Set Names ‘gb2312’

在之後全部這個鏈接上的查詢,MySQL都會自動把數據庫中的數據轉換成gb2312編碼格式傳過來。

2、錯誤寫入

現象:一個網頁或程序向一個MySQL數據庫中寫數據,寫完後,這個網頁或程序本身能夠正常讀取數據,而從其它客戶端或網頁中讀取數據都是亂碼。

分析:其它的正常的客戶端出現亂碼,說明數據庫中的字符編碼不對。寫數據的那個網頁能正常讀取,是由於寫和讀都用了錯誤的編碼格式,將錯就錯,反而能讀出正確的數據了。好比數據庫中設定的字符集爲UTF8,而網頁使用gb2312編碼執行了插入數據的SQL,那麼MySQL就會把這些gb2312的編碼當成是UTF8的編碼寫進數據庫。當其它客戶端訪問數據時,會按系統的設定,以UTF8 格式讀取數據,而數據實際上是使用gb2312編碼的,結果就出現了亂碼。只有寫數據的那個網頁會把這些數據當成gb2312的,也只有那個網頁能正常顯示數據。

解決辦法:同第一條,即:使用Set Names指令設定鏈接字符集。

在設定了鏈接字符體的鏈接上執行數據操做,全部的數據都將被MySQL自動、正確地轉換爲數據庫中設定的編碼格式保存。

經過以上兩點,咱們能夠看到,只要在鏈接MySQL時,正確地設定了字符集,不管數據庫自己是使用什麼格式編碼的,都能獲得正確的結果。也許有人會覺得寫數據時設定的字符集必需和讀數據時一致,事實上徹底沒有必要。程序所要作的只是告訴 MySQL,目前操做MySQL使用的是什麼字符集便可。由於MySQL會自動完成以下的轉換工做:

寫數據庫時用的字符集-->存諸數據的字符集-->讀取數據的字符集。

筆者覺得MySQL對多語言字符集的處理是很是優秀的,而且每次創建到MySQL的鏈接都會馬上使用Set Names設定字符集,然而最近仍是出現了一回亂碼,以下面所述。

3、無知的程序包

現象:使用C#編程,使用MySQL提供的鏈接程序庫包訪問數據庫,使用 MySqlConnection類鏈接數據庫,鏈接以後馬上調用Set Names設定鏈接字符串,而後使用MySqlCommand類執行SQL,並使用MySqlDataReader讀取數查詢結果。然而,當我調用 MySqlDataReader的成員方法GetString獲取數據的時候,發現獲得的全是亂碼。百思不得其解。

分析:經仔細檢查,確信問題沒有出在MySQL鏈接上面,這時我想到了C#中對 string類型的處理。在C#中字符串和C/C++中有很大不一樣。在C/C++中一個字符就是一個字節,而在C#中,按不一樣的編碼格式,一個字符也能夠是多個字節的。好比」啊」就是一個字符,若是一個字符串s=」啊」; 那麼s的Length屬性爲1,而不是C/C++中的2。我想MySQL程序包也許並不知道鏈接上傳過來的字符是什麼編碼的,它由於無知,因此只是按單字節字符把這些數據組織成一個string,這個生成的string就是我獲得的亂碼。事實上也的確是這樣。

解決辦法:把這些數據從新組織起來,而後使用正確的編碼方法從新生成string。C#中System.Text包內的Encoding類提供了字符集的編/解碼方法。

1)首先仍是設定鏈接字符集,以確認收到的字符的編碼方式。
2)把GetString獲得的字符串轉換到byte數組中。
3)使用Systec.Text.Encoding包中相應字符集的解碼方法GetString獲得新的字符串。

爲了通用性,咱們使用System.Text.Encoding的默認字符集。鏈接數據庫時,設置數據庫鏈接字符集使用的SQL指令strSetCharset爲以下值:
string strSetCharset = 「Set Names 」 + System. Text. Encoding .Default. HeaderName;

在獲取數據時,使用下面的函數獲得真正的字符串:

private string DBStringToNormal(string dbStr)
       {
         byte[] str = new byte[dbStr.Length];
         for (int i = 0; i < dbStr.Length; ++i)
            str[i] = (byte)(dbStr[i]);
    return System.Text.Encoding.Default.GetString(str, 0, dbStr.Length);
}
-----------------------------------------------------------------------------------------------------------------數據庫

看到這個文章受到啓發,重要的一句是:編程

經過以上兩點,咱們能夠看到,只要在鏈接MySQL時,正確地設定了字符集,不管數據庫自己是使用什麼格式編碼的,都能獲得正確的結果。也許有人會覺得寫數據時設定的字符集必需和讀數據時一致,事實上徹底沒有必要。程序所要作的只是告訴 MySQL,目前操做MySQL使用的是什麼字符集便可。由於MySQL會自動完成以下的轉換工做:

寫數據庫時用的字符集-->存諸數據的字符集-->讀取數據的字符集。c#

 

由此想個人問題多是寫入時聲明的個人字符編碼與我實際的不符,C#中字符默認編碼爲GB2312,因而程序改動以下:數組

1:在連接字符加入字符編碼聲明函數

<add key="mysqlconstr" value="UserId=root;Allow Zero Datetime=true;Charset=gb2312;Host=125.*.*.*;Database=dbname;Password=123456"/>字體

向mysql說明個人字符編碼是gb2312, 不要搞錯編碼

2:在數據庫類中每一插入數據語句前加入編碼聲明

cmd = new MySqlCommand("set names gb2312;"+sql,conn);
    cmd.ExecuteNonQuery();   

期待已久的中文終於順利寫入了!

相關文章
相關標籤/搜索