2010-10-25 25 views
1

我有一個字符串,我從Word文檔讀入。我認爲它是在「Cp1252」編碼。 Java使用UTF8。如何解析與java編碼不同的字符串

如何在Cp1252中爲那些特殊字符搜索該字符串並將其替換爲適當的UTF8字符?

具體而言,我想,以取代「短劃線」字符與普通「 - 」

下面的代碼塊需要其從Word文檔來的projDateString,並試圖做這樣的事情

char[] test = projDateString.getBytes("Cp1252"); 
    for(int i = 0; i < test.length; i++){ 
    System.out.println "test["+ i + "] = " + Integer.toHexString((byte)test[i]); 
    } 
    String projDateString2 = new String(test); 
    projDateString2.replaceAll("\0x96", "\u2013"); 
    System.out.println("projDateString2: " + projDateString) 

我不確定我是否正確設置了projDateString2。正如你所看到的,當我使用Cp1252編碼對字符串進行getBytes時,該短劃線的十六進制值是ffffff96。如果我用UTF8 getBytes,它將以3個十六進制值而不是一個來表示。

這給了我下面的輸出:

test[0] = 30 
test[1] = 38 
test[2] = 2f 
test[3] = 32 
test[4] = 30 
test[5] = 31 
test[6] = 30 
test[7] = 20 
test[8] = ffffff96 
test[9] = 20 
test[10] = 50 
test[11] = 72 
test[12] = 65 
test[13] = 73 
test[14] = 65 
test[15] = 6e 
test[16] = 74 
projDateString2: 08/2010 ΓÇô Present 

正如你所看到的,更換什麼也沒做,和println的仍然給我的垃圾字符,而不是一個純文本「 - 」

+0

可能的重複[編碼轉換在java中](http://stackoverflow.com/questions/229015/encoding-conversion-in-java) – kamaci 2012-08-26 14:25:24

回答

13

Java字符串是總是使用UTF-16的,至少就API而言......但您通常可以將它們視爲「Unicode」。它們是UTF-16的事實只有在涉及基本多語言平面以外的字符時才真正相關,即Unicode值高於U + FFFF。他們必須在Java中代表替代對。但我認爲你不需要擔心你的情況。因此,只要將字符串中的值視爲「Unicode文本」,而不使用特定的編碼...尤其是,在UTF-8或CP1252中,確切地說不是。這些是用於將二進制數據(例如字節數組)轉換成文本數據(例如字符串)的編碼。

你不應該使用String.getBytes()new String(byte[])沒有指定的編碼 - 問題。那些總是使用平臺默認編碼 - 這幾乎是總是錯誤的選擇。

你說你「有一個字符串,我從一個Word文檔中讀入」 - 你是怎麼讀的?它是如何開始生活的?

如果你有字節,你知道相關的編碼,你應該使用:

String text = new String(bytes, encoding); 

你不應該不得不面對已經使用了錯誤的編碼創建一個字符串 - 如果你到那個階段,你幾乎要約束冒着信息損失的風險。儘可能早地解決問題,而不是稍後嘗試修復數據。

The next要明白的是,Java中的String類是不可變的。在字符串上調用replaceAll將不會更改現有字符串。它將返回一個新的字符串,並進行替換。

所以這種說法:

projDateString2.replaceAll("\0x96", "\u2013"); 

從未做你想做的。即使一切正確,你應該使用:

projDateString2 = projDateString2.replaceAll("\0x96", "\u2013"); 

(或類似的東西)。我不認爲實際上做你想要的東西,但是當你把所有的東西都解決掉時你需要知道它。

+0

由於我在編寫時進行了編輯,因此我會重新考慮此評論。 – Derek 2010-10-25 16:35:12

+0

沒有指定提到的方法的編碼只是意味着它們使用默認的平臺編碼。如果未指定'-Dfile.encoding',則爲UTF-8。 – Bozho 2010-10-25 16:39:47

+0

@Bozho:它是* some *平臺上的UTF-8,但不是全部。依靠它基本上是一個不好的舉措。我將編輯這個。 – 2010-10-25 16:41:00

2

轉換一般是通過類似的方式完成:

String properlyEncoded = 
    new String(original.getBytes(originalEncoding), newEncoding); 

請注意,在轉換過程中某些信息不會丟失。

+0

好吧,所以我沒有String projDateString2 = new String(projDateString.getBytes(「 Cp1252「),」UTF-16「);並且仍然無法使replaceAll正常工作 – Derek 2010-10-25 16:33:39

+0

儘管這種轉換很容易損失,因爲原始的不正確轉換很容易丟失信息。 – 2010-10-25 16:41:48

+0

@Jon Skeet是真的。但我認爲,你無法防止這種損失。 – Bozho 2010-10-25 16:43:30

1

首先,您需要確保您正確地從CP1252字節轉換爲Java的character representation(即UTF-16)。由於您正在使用庫來解析.docx文件,因此可能發生了這種情況。

現在,您只需撥打projDateString.replace('\u2013', '-')並執行返回值。因爲你沒有使用正則表達式,所以不需要replaceAll()

+0

我正在使用docx4j打開word文檔。它似乎在使用FileInputStream,並且可以在這裏看到加載方法:http://dev.plutext.org/trac/docx4j/browser/trunk/docx4j/src/main/java/org/docx4j/openpackaging/packages/ OpcPackage.java – Derek 2010-10-25 16:47:31

+0

感謝您的提示abotu返回值 - 我已經在代碼中輸入正確..只是沒有成爲我的SO問題 – Derek 2010-10-25 16:47:57

+0

更新我的答案,你試圖從「恩短跑」到「 - 「,對嗎?否則,你將不得不交換replace()參數。 – adietrich 2010-10-25 22:43:25