JAVA 資料庫連接編碼問題

來源:互聯網
上載者:User

轉載:http://hi.baidu.com/sosyq_bd/blog/item/c42d8330b8db7557ad4b5f94.html

java中String的編碼格式為unicode,如果要將中文插入mysql,則表中字元列的編碼屬性應該設為utf-8.

create table seugs( 

  number int(11) default NULL,

  name nchar(10) default NULL,

  sex nchar(4) default NULL,

  home nchar(100) default NULL,

  college nchar(50) default NULL,

  benke nchar(50) default NULL,

  birth date default NULL,

  rxtime date default NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8。

在java串連mysql時,串連語句可設定字元集,文法如下,注意表名跟屬性設定之間用問號串連

conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8", "root", "syq"); 

如果使用命令列或者IDE工具直接執行SQL語句,如果查詢條件裡有中文,則還應該設定MYSQL的字元編碼。原因如下:

 MySQL處理串連時,外部串連發送過來的SQL請求會根據以下順序進行轉換:
character_set_client             //客戶串連所採用的字元集
        |
character_set_connection       //MySQL串連字元集
        |
character_set_database         //資料庫所採用的字元集(表,列)
        |
character_set_results           //客戶機顯示所採用的字元集

一. 產生亂碼的根本原因在於:
1.客戶機沒有正確地設定client字元集,導致原先的SQL語句被轉換成connection所指字元集,而這種轉換,是會丟失資訊的,如果client是utf8格式,那麼如果轉換成gb2312格式,這其中必定會丟失資訊,反之則不會丟失。一定要保證connection的字元集大於client字元集才能保證轉換不丟失資訊。
2. 資料庫字型沒有設定正確,如果資料庫字型設定不正確,那麼connection字元集轉換成database字元集照樣丟失編碼,原因跟上面一樣。

設定方法:

在my.ini或者my.cnf中修改這兩個參數

[mysqld]
default-character-set=utf8
[mysql]
default-character-set=utf8

轉載一個java編碼問題的網頁

Java與Unicode:

Java的class檔案採用utf8的編碼方式,JVM運行時採用utf16

Java的字串是unicode編碼的。

總之,Java採用了unicode字元集,使之易於國際化。

 

Java支援哪些字元集:

 

即Java能識別哪些字元集並對它進行正確地處理?

查看Charset 類,最新的JDK支援160種字元集。可以通過static方法availableCharsets拿到所有Java支援的字元集。

Java代碼  

assertEquals(160, Charset.availableCharsets().size());    Set<String> charsetNames = Charset.availableCharsets().keySet();    assertTrue(charsetNames.contains("utf-8"));  assertTrue(charsetNames.contains("utf-16"));  assertTrue(charsetNames.contains("gb2312"));    assertTrue(Charset.isSupported("utf-8"));  

 

需要在哪些時候注意編碼問題?

 

1. 從外部資源讀取資料:

這跟外部資源採取的編碼方式有關,我們需要使用外部資源採用的字元集來讀取外部資料:

Java代碼  

InputStream is = new FileInputStream("res/input2.data");  InputStreamReader streamReader = new InputStreamReader(is, "GB18030");
 

這裡可以看到,我們採用了GB18030編碼讀取外部資料,通過查看streamReader的encoding可以印證:

Java代碼  

assertEquals("GB18030", streamReader.getEncoding());  

正是由於上面我們為外部資源指定了正確的編碼,當它轉成char數組時才能正確地進行解碼(GB18030 -> unicode):

 

Java代碼  

char[] chars = new char[is.available()];  streamReader.read(chars, 0, is.available());   

但我們經常寫的代碼就像下面這樣:

Java代碼  

InputStream is = new FileInputStream("res/input2.data");  InputStreamReader streamReader = new InputStreamReader(is);
 

這時候InputStreamReader採用什麼編碼方式讀取外部資源呢?Unicode?不是,這時候採用的編碼方式是JVM的預設字元集,這個預設字元集在虛擬機器啟動時決定,通常根據語言環境和底層作業系統的 charset 來確定。可以通過以下方式得到JVM的預設字元集:

Java代碼  

Charset.defaultCharset();   

為什麼要這樣?因為我們從外部資源讀取資料,而外部資源的編碼方式通常跟作業系統所使用的字元集一樣,所以採用這種預設是可以理解的。

好吧,那麼我通過我的IDE Ideas建立了一個檔案,並以JVM預設的編碼方式從這個檔案讀取資料,但讀出來的資料竟然是亂碼。為何?呵呵,其實是因為通過Ideas建立的檔案是以utf-8編碼的。要得到一個JVM預設編碼的檔案,通過手工建立一個txt檔案試試吧。

 

2. 字串和位元組數組的相互轉換 

我們通常通過以下代碼把字串轉換成位元組數組:

Java代碼  

"string".getBytes();  

但你是否注意過這個轉換採用的編碼呢?其實上面這句代碼跟下面這句是等價的:

Java代碼  

"string".getBytes(Charset.defaultCharset());  

也就是說它根據JVM的預設編碼(而不是你可能以為的unicode)把字串轉換成一個位元組數組。

反之,如何從位元組數組建立一個字串呢?

Java代碼  

new String("string".getBytes());  

同樣,這個方法使用平台的預設字元集解碼位元組的指定數組(這裡的解碼指從一種字元集到unicode)。

 

字串編碼迷思:

Java代碼  

new String(input.getBytes("ISO-8859-1"), "GB18030")   

上面這段代碼代表什嗎?有人會說: “把input字串從ISO-8859-1編碼方式轉換成GB18030編碼方式”。如果這種說法正確,那麼又如何解釋我們剛提到的java字串都採用unicode編碼呢?

這種說法不僅是欠妥的,而且是大錯特錯的,讓我們一一來分析,其實事實是這樣的:我們本應該用GB18030的編碼來讀取資料並解碼成字串,但結果卻採用了ISO-8859-1的編碼,導致產生一個錯誤的字串。要恢複,就要先把字串恢複成原始位元組數組,然後通過正確的編碼GB18030再次解碼成字串(即把以GB18030編碼的資料轉成unicode的字串)。注意,字串永遠都是unicode編碼的。

但編碼轉換並不是負負得正那麼簡單,這裡我們之所以可以正確地轉換回來,是因為 ISO8859-1 是單位元組編碼,所以每個位元組被按照原樣 轉換為String ,也就是說,雖然這是一個錯誤的轉換,但編碼沒有改變,所以我們仍然有機會把編碼轉換回來!

總結:

所以,我們在處理java的編碼問題時,要分清楚三個概念:Java採用的編碼:unicode,JVM平台預設字元集和外部資源的編碼。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.