2010-05-04 102 views
10

我有一些問題得到了一些法語文本轉換爲UTF8,以便它可以正確顯示,無論是在一個控制檯,文本文件或GUI元素。UTF8字符編碼在Java中

原始字符串

HANDICAP╔ES

這應該是

HANDICAPÉES

下面的代碼片段,顯示我如何使用jackcess數據庫驅動程序讀取在Eclipse/Linux環境中的Acccess MDB文件中。

Database database = Database.open(new File(filepath)); 
Table table = database.getTable(tableName, true); 
Iterator rowIter = table.iterator(); 
while (rowIter.hasNext()) { 
    Map<String, Object> row = this.rowIter.next(); 
    // convert fields to UTF 
    Map<String, Object> rowUTF = new HashMap<String, Object>(); 
    try { 
     for (String key : row.keySet()) { 
      Object o = row.get(key); 
      if (o != null) { 
       String valueCP850 = o.toString(); 
       // String nameUTF8 = new String(valueCP850.getBytes("CP850"), "UTF8"); // does not work! 
       String valueISO = new String(valueCP850.getBytes("CP850"), "ISO-8859-1"); 
       String valueUTF8 = new String(valueISO.getBytes(), "UTF-8"); // works! 
       rowUTF.put(key, valueUTF8); 
      } 
     } 
    } catch (UnsupportedEncodingException e) { 
     System.err.println("Encoding exception: " + e); 
    } 
} 

在你會看到,我想直接轉換爲UTF-8,這似乎並沒有工作的代碼,所以我必須做一個雙轉換。另請注意,使用jackcess驅動程序時似乎沒有指定編碼類型的方法。

感謝, 凸輪

+1

這不是UTF-8,而是CP850。 – Joey 2010-05-04 15:44:43

+0

你是說原始字符串是CP850嗎?我意識到原始字符串不是UTF-8,儘管我不確定哪一種確切的編碼。我試圖將其轉換爲UTF-8,以便正確顯示。我的理解是,UTF-8支持É字符。 謝謝。 – cambo 2010-05-04 16:07:58

+3

當您在CP1252中使用'É'並將其解釋爲CP850時,就會得到'╔'。 – Joey 2010-05-04 16:13:37

回答

9

基於新信息的新分析。
它看起來像你的問題是之前的文本編碼它存儲在Access數據庫中。它似乎被編碼爲ISO-8859-1或windows-1252,但被解碼爲cp850,導致字符串HANDICAP╔ES被存儲在數據庫中。

從DB正確檢索到該字符串後,您現在試圖反轉原始編碼錯誤並恢復字符串,因爲它應該已經存儲:HANDICAPÉES。而你正在努力完成的,與這條線:

String valueISO = new String(valueCP850.getBytes("CP850"), "ISO-8859-1"); 

getBytes("CP850")轉換的字符的字節值0xC9和String構造解碼,按照ISO-8859-1,導致性格É。下一行:

String valueUTF8 = new String(valueISO.getBytes(), "UTF-8"); 

......什麼都不做。 getBytes()在您的Linux系統上對平臺默認編碼中的字符串進行編碼,該編碼爲UTF-8。然後,String構造函數使用相同的編碼解碼它。刪除該行,你仍然應該得到相同的結果。

更重要的是,您嘗試創建「UTF-8字符串」被誤導了。你不需要關心Java字符串的編碼 - 它們總是UTF-16。將文本引入Java應用程序時,只需確保使用正確的編碼對其進行解碼即可。

如果我的分析是正確的,您的Access驅動程序正確解碼;問題出在另一端,甚至在數據庫甚至出現在圖片之前。 這就是你需要解決的問題,因爲那個破解不能算在所有情況下工作。


原分析的基礎上,沒有信息。: -/
如果您在控制檯上看到HANDICAP╔ES,則可能沒有問題。鑑於此代碼:

System.out.println("HANDICAPÉES"); 

的JVM轉換(Unicode)的字符串來平臺默認的編碼,窗口1252,將其發送到控制檯前。然後控制檯使用其默認編碼自己的進行解碼,這恰好是cp850。所以控制檯顯示錯誤,但這很正常。如果你想讓它正確顯示,你可以用這個命令更改控制檯的編碼:

CHCP 1252 

要顯示GUI元素的字符串,如一個JLabel,你沒有做什麼特別的。只要確保你使用的字體可以顯示所有的字符,但這不應該是法語的問題。

至於寫入文件,只需指定所需的編碼,當您創建編劇:

OutputStreamWriter osw = new OutputStreamWriter(
    new FileOutputStream("myFile.txt"), "UTF-8"); 
+0

我想我應該更清楚我的開發環境。對於開發,我在Ubuntu Linux機器上使用Eclipse。無論從Eclipse控制檯還是通過常規終端控制檯運行它,我都可以得到相同的結果。 我們使用jackcess Java API來讀取Access MDB數據庫文件。似乎沒有辦法指定jackcess驅動程序的默認編碼,所以我必須按照上面所述進行轉換。 我試圖直接輸出字符串到一個GUI元素(JLabel,JTextField),但這也沒有幫助。 – cambo 2010-05-08 15:44:44

+0

是的,這似乎是一個相當奇特的問題,其中原始問題沒有提示。如果我們能夠看到您用於檢索數據的實際代碼,它可能會有所幫助。並且不要試圖在評論中提出這個問題 - 你已經看到了它的效果。編輯問題並將其放在那裏。 – 2010-05-08 20:42:42

+0

好的,我編輯了這個問題來顯示我用來檢索數據的代碼示例。謝謝。 – cambo 2010-05-11 18:34:47

8
String s = "HANDICAP╔ES"; 
System.out.println(new String(s.getBytes("CP850"), "ISO-8859-1")); // HANDICAPÉES 

這顯示正確的字符串值。這意味着它是原本編碼/解碼與ISO-8859-1和編碼與CP850(原CP1252又名的Windows ANSI然後錯誤在評論指出確實也是可能的,因爲É具有相同的代碼點出現在ISO-8859- 1)。

對準你的環境,二元管道使用所有一個相同的字符編碼。你不能也不應該在它們之間進行轉換。這樣就會冒失去非ASCII範圍內的信息的風險。

注意:不要使用上面的代碼片段,以「修復」的問題!這不是正確的解決方案。


更新:你顯然還是有問題掙扎。我重複回答的重要組成部分:

  1. 對準你的環境,二元管道使用所有一個相同字符編碼。

  2. 你可以不是而應該不是它們之間進行轉換。你會冒險這種方式失去信息在非ASCII範圍內。

  3. 不是使用上面的代碼片段來「解決」問題!那不會是正確的解決方案。

要解決此問題,您需要選擇字符編碼X,您希望在整個應用程序中使用字符編碼X.我建議UTF-8。更新MS Access以使用編碼X.更新您的開發環境以使用編碼X.更新java.io讀者和作者在您的代碼中以使用編碼X.更新您的編輯器以使用編碼X讀/寫文件。更新應用程序的用戶界面以使用編碼X.做不是使用Y或Z或任何在某個步驟。如果字符是已在某些數據存儲(MS Access,文件等)中已損壞,那麼您需要通過手動替換數據存儲中的字符來修復它。不要爲此使用Java。

如果您實際上使用「命令提示符」作爲用戶界面,那麼您實際上已經丟失。它不支持UTF-8。正如評論和評論中鏈接的文章中所建議的,您需要創建一個Swing應用程序,而不是依賴於受限制的命令提示符環境。

+0

感謝您的回覆。我收到的數據在Access數據庫中,所以我無法控制它最初的編碼方式。我想我需要閱讀它並在做任何事之前將其轉換爲適當的格式。 此外,我們正試圖在我們的應用程序中標準化和使用UTF-8。 UTF-8是否不支持這些字符? – cambo 2010-05-04 16:26:27

+2

您需要指示JDBC驅動程序和/或數據庫使用正確的編碼(數據庫本身正在使用的編碼!)。如果你理解我的意思,UTF-8肯定支持這些字符,但用不同的二進制表示。字符就是 - 作爲一切 - 以字節形式傳輸。只是因爲電腦不瞭解其他任何東西。 [本文](http://balusc.blogspot.com/2009/05/unicode-how-to-get-characters-right.html)可能有助於更好地理解問題之下的問題。 – BalusC 2010-05-04 16:28:15

+0

感謝您提供的信息和鏈接,這是一篇很棒的文章! – cambo 2010-05-04 17:32:54

-1

使用「ISO-8859-1」幫我對付法國本地字符。

0

建立連接時可以指定編碼。這種方式是完美的,並解決我的編碼問題:

DatabaseImpl open = DatabaseImpl.open(new File("main.mdb"), true, null, Database.DEFAULT_AUTO_SYNC, java.nio.charset.Charset.availableCharsets().get("windows-1251"), null, null); 
    Table table = open.getTable("FolderInfo");