瀏覽量:787
2010-02-04 15:26
使用mysql儲存中文資料時,經常會遇到亂碼問題。產生亂碼的原因很多,在筆者以為對mysql的字符集處理已經很有了解的時候,使用c#程式設計時,竟再 一次遇到了亂碼。聯想到前幾天一位同事在使用jdbc訪問mysql時遇到的中文亂碼問題,決定對mysql中文亂碼問題的產生場景進行一次總結。
一、錯誤讀出
現象:乙個已經存在資料的mysql資料庫,該資料庫的資料用系統中其它軟體、網頁檢視均正常,使用mysqlcc之類的客戶端檢視也正常,可是在新寫的網頁中總是顯示亂碼。
分析:其它系統都可以正常檢視資料,說明資料本身是沒有問題的。在網頁中顯示亂碼,一定是網頁的編碼字符集和獲取到的資料的編碼字符集不一至。比如資料庫 的字符集是utf8的,而網頁的字符集是gb2312的,那麼網頁就會把utf8編碼的字型串當作gb2312的來處理,結果產生亂碼。
解決辦法:在連線資料庫時,設定連線字符集,使連線字符集和當前網頁或客戶端程式使用的字符集一致。可以使用mysql的set names指令設定連線字符集。假設網頁的字型集為gb2312。在連線mysql後,在連線上執行如下sql語句:
set names 『gb2312』
在以後所有這個連線上的查詢,mysql都會自動把資料庫中的資料轉換成gb2312編碼格式傳過來。
二、錯誤寫入
現象:乙個網頁或程式向乙個mysql資料庫中寫資料,寫完後,這個網頁或程式自己可以正常讀取資料,而從其它客戶端或網頁中讀取資料都是亂碼。
分析:其它的正常的客戶端出現亂碼,說明資料庫中的字元編碼不對。寫資料的那個網頁能正常讀取,是因為寫和讀都用了錯誤的編碼格式,將錯就錯,反而能讀出 正確的資料了。比如資料庫中設定的字符集為utf8,而網頁使用gb2312編碼執行了插入資料的sql,那麼mysql就會把這些gb2312的編碼當 成是utf8的編碼寫進資料庫。當其它客戶端訪問資料時,會按系統的設定,以utf8 格式讀取資料,而資料其實是使用gb2312編碼的,結果就出現了亂碼。只有寫資料的那個網頁會把這些資料當成gb2312的,也只有那個網頁能正常顯示 資料。
解決辦法:同第一條,即:使用set names指令設定連線字符集。
在設定了連線字元體的連線上執行資料操作,所有的資料都將被mysql自動、正確地轉換為資料庫中設定的編碼格式儲存。
通過以上兩點,我們可以看到,只要在連線mysql時,正確地設定了字符集,無論資料庫本身是使用什麼格式編碼的,都能得到正確的結果。也許有人會以為寫 資料時設定的字符集必需和讀資料時一致,事實上完全沒有必要。程式所要做的只是告訴 mysql,目前操作mysql使用的是什麼字符集即可。因為mysql會自動完成如下的轉換工作:
寫資料庫時用的字符集-->存諸資料的字符集-->讀取資料的字符集。
筆者以為mysql對多語言字符集的處理是非常優秀的,並且每次建立到mysql的連線都會立刻使用set names設定字符集,然而最近還是出現了一回亂碼,如下面所述。
三、無知的程式包
現象:使用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)
問題解決。在使用jdbc訪問mysql時,也會有這樣的問題,可以用類似的方法解決。
JDBC操作Mysql資料庫表時中文亂碼的解決方案
通過jdbc運算元據庫表時,如果記錄中有中文,可能會碰到亂碼的問題。主要原因是字元編碼 characterencoding 不正確,原因如下 1 eclipse中設定檔案的字元編碼格式與資料庫等不一致 2 在資料庫伺服器上建立資料庫和表的時候沒有選擇支援中文的編碼方式 3 建立jdbc連線時沒有指明...
MySQL資料庫以及SQL語法基礎 中文亂碼
sql structured query language結構化查詢語言。一 ddl 資料定義語言 data definition language 建庫 建表 設定約束等 create drop alter 二 dcl 資料控制語言 data controll language 資料授權,收回授權...
c 訪問mysql資料庫
c 訪問mysql資料庫,實現 show database功能 連線之前。先用mysql init初始化mysql連線控制代碼 1.mysql init mysql 使用mysql real connect連線server,其引數依次為mysql控制代碼。serverip位址。登入mysql的use...