2011-12-13 84 views
1

我的POST數據包含日文字符串AKB48 ネ申テレビ シーズン3,在jQuery中定義爲dataJava POST數據到mySQL UTF-8編碼問題

$("#some_div").load("someurl", { data : "AKB48 ネ申テレビ シーズン3"}) 

POST數據發送到Java Servlet的:

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8"); 

我的程序將其保存到MySQL,但數據被保存到數據庫後,就變成了:

AKB48 u30CDu7533u30C6u30ECu30D3 u30B7u30FCu30BAu30F33

我該怎麼辦,如果我想要將它保存爲UTF-8?我所有的文件都是UTF-8。

MySQL的編碼是UTF8和這裏是代碼

String sql = "INSERT INTO Inventory (uid, item_id, item_data, ctime) VALUES (" 
       + inventory.getUid() + ",'" 
       + inventory.getItemId() + "','" 
       + StringEscapeUtils.escapeJava(inventory.getItemData()) + "',CURRENT_TIMESTAMP)"; 
    Statement stmt = con.createStatement(); 
    int cnt = stmt.executeUpdate(sql); 
+0

是你在utf8中的mysql數據庫嗎?你如何堅持mysql,直接SQL或休眠等?而且,由於它正確地保存了代碼點,因此可能是你只是錯誤地查看了它 –

+0

是的,mySQL都是utf8 – bbnn

回答

3

從上面的示例中,我可以驗證日語字符串是否正確保存到MySQL數據庫,但是作爲escaped Unicode

我會爲了檢查下列項目:

  1. 是你的表和列所有設置有一個UTF8字符集和校對規則?即, CHARACTER SET utf8 COLLATE utf8_general_ci
  2. 是否在POST之前明確設置了字符集編碼? request.setCharacterEncoding("UTF-8");
  3. 你是否爲數據庫連接設置字符編碼?即,jdbc:mysql://localhost:3306/YOURDB?useUnicode=true&characterEncoding=UTF8

正如其他人已經指出,你不應該使用getBytes詭計。它肯定會搞亂POST的值。

編輯

不要使用StringEscapeUtils.escapeJava,因爲這會變成你的字符串轉換成Unicode的逃脫。這就是將AKB48 ネ申テレビ シーズン3轉化爲AKB48 u30CDu7533u30C6u30ECu30D3 u30B7u30FCu30BAu30F33的原因。

+0

我做了第1步和第2步,但沒有3,因爲我正在使用\t \t \t DataSource dc =(DataSource)ctx.lookup(「java:comp/env/jdbc/databasename」); 類型的連接 – bbnn

+0

@bn。,我的第3點是顯式設置數據庫連接的字符集編碼。如果你不這樣做,你可能會用不正確的編碼將數據保存到數據庫中。 '(DataSource)ctx.lookup'用於查找數據源,這完全是另一回事。我強烈建議你重新檢查你的數據庫連接是如何被創建的。 – buruzaemon

+0

您需要將它們設置爲數據源配置中的連接屬性。哦,請擺脫所有'新的字符串(字符串,字符集)'和'string.getBytes(charset)'廢話。 – BalusC

0

爲什麼你不只是提取參數的值一樣this.request.getParameter("data")

使用URL編碼正確發送您的數據,其中每個unicode字符被替換爲其代碼。然後你必須得到參數的值。當您使用ISO-8859-1請求字節時,實際上是在破壞您的數據,因爲如果以文本形式編碼,字符串將被表示爲序列。

+0

雖然它會破壞一些數據,但他的角色不在字符範圍內。所以這不是這個例子中的問題。他正在將正確的碼點保存到他的MYSQL中,這樣我們就可以看到它被正確解釋了。但我使用alex,你應該在你的tomcat設置中使用'URIEncoding =「UTF-8」',並讓它處理參數編碼。 –

+0

我不知道jquery load使用了一個帖子。 'URIEncoding =「UTF-8」'沒有必要。 –

0

什麼是線

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8"); 

你正在改變中國的(或至少非歐美)字符的點到使用ISO-8859-1編碼字節。當然這是行不通的,因爲ISO-8859-1編碼不支持中文字符。然後,您使用UTF-8編碼從字節中構建一個應該表示ISO-8859-1編碼字符的新字符串。這再一次沒有任何意義。 UTF-8和ISO-8859-1不是一回事,只有一小部分字符在兩種格式中都具有相同的編碼。

只需使用

String data = this.request.getParameter("data"); 

,一切都應該是好的,前提是在MySQL表中的列使用支持這些字符的編碼。

編輯:

現在

你已經向我們展示應用於數據庫中插入數據的代碼,我知道這一切都來自(上述要點仍然是有效的,雖然)。你在做

StringEscapeUtils.escapeJava(inventory.getItemData()) 

有什麼意義? escapeJava用於接收字符串並轉義特殊字符以使其成爲有效的Java String文字。它與SQL無關。使用準備好的語句:

String sql = "INSERT INTO Inventory (uid, item_id, item_data, ctime) VALUES (?, ?, ?, CURRENT_TIMESTAMP); 
PreparedStatement stmt = con.prepareStatement(); 
stmt.setInteger(1, inventory.getUid()); // or setLong, depending on the type 
stmt.setString(2, inventory.getItemId()); 
stmt.setString(inventory.getItemData()); 
int cnt = stmt.executeUpdate(); 

PreparedStatement將負責正確轉義特殊的SQL字符。它們是SQL注入攻擊的最佳工具,並且在查詢有參數時應始終使用,特別是如果參數來自最終用戶。見http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html

+0

如果我只使用String data = this.request.getParameter(「data」); 變成不同的東西,如:AKB48 u00E3u0083u008Du00E7u0094u00B3u00E3u0083u0086u00E3u0083u00ACu00E3u0083u0093 u00E3u0082u00B7u00E3u0083u00BCu00E3u0082u00BAu00E3u0083u00B33 – bbnn

+0

告訴我們的MySQL列的編碼,並告訴我們用來保存在數據庫中的字符串代碼。 –

+0

其utf8我編輯了問題,雖然 – bbnn

0

Java字符串存儲在UTF-16中。所以,這樣的代碼:

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8"); 

解碼UTF-16的字符串(其已經從UTF-8在HTTP協議中重新編碼)成使用ISO-8859-1的字符集二進制數組,並重新使用UTF-8字符集編碼二進制數組。這幾乎肯定不是你想要的。

當你使用它時會發生什麼?

String data = this.request.getParameter("data"); 
System.out.println(data); 

如果第二行產生錯誤的數據,那麼你的問題可能在jQuery中。確定你確實在你的jQuery的要求越來越統一:

System.out.println(this.request.getHeader("Content-Encoding")); 

如果它不產生壞的數據,但數據不能正確存儲在MySQL中,你的問題是在數據庫級別。確保你的列類型支持unicode字符串。

+0

System.out.println(this.request。getHeader( 「內容編碼」)); 返回我null – bbnn