2013-02-03 149 views
1

我有一個「windows1255」編碼的字符串,沒有任何安全的方式,我可以將其轉換爲「UTF-8」編碼問題

字符串,反之亦然?

一般是有一種安全的方式(意思是數據不會被損壞)在Java中

編碼之間的轉換?

 str.getBytes("UTF-8"); 
    new String(str,"UTF-8"); 

如果原始字符串未被編碼爲「UTF-8」,數據是否會被損壞?

+0

你可能有一個看看這個: http://stackoverflow.com/questions/4016671/how-to-parse-a-string-that-is-in -a-different-encoding-from-java – Danyel

回答

2

在Java中,您可以不使用正確編碼的String對象作爲UTF-16以外的任何其他對象 - 因爲這是由規範定義的對象的唯一編碼。當然,你可以做一些不喜歡的事情,比如把一個char []放在一個char []中,並且從中創建一個String,但是事情很快就會出錯。

你可以用各種不同的方式編碼byte [],並且可以使用帶有字符集的構造函數以及與代碼中的getBytes一起將它們轉換爲String。

因此,您可以使用String作爲中間值進行轉換。我不知道JDK有任何方法可以進行直接轉換,但是在實踐中該中間體可能不會太昂貴。

關於往返轉換 - 通常不是真的,您可以在不丟失數據的情況下在編碼之間進行轉換。只有少數編碼可以處理全部的Unicode字符(例如UTF系列,GB18030等) - 而許多遺留字符集僅編碼一小部分子集。除非確定輸入屬於可表示集,否則無法安全地往返這些字符集而不會丟失數據。

1

字符串試圖是一個抽象字符序列,它沒有從其用戶的視角 的任何編碼。當然,它必須有一個內部編碼,但這是一個實現細節。

將String編碼爲UTF-8是沒有意義的,然後將結果解碼爲UTF-8。這將是任何操作,因爲:

(new String(str.getBytes("UTF-8"), "UTF-8")).equals(str) == true; 

但也有情況下字符串抽象分崩離析和上面的將是一個「有損」的轉換。由於內部的 實現細節,字符串可以包含不能用UTF-8(或任何編碼 ,包括內部UTF-16編碼*)表示的不成對的UTF-16替代品。所以它們會在編碼中丟失,並且當你解碼時,你會得到沒有無效的不成對代理的原始字符串。

我可以從你的問題的唯一的事情是,你必須從解釋二進制數據的Windows-1255,它應該在UTF-8已經解釋的字符串結果。 要解決這個問題,您必須轉到此源代碼並明確使用UTF-8解碼。

但是,如果你的字符串結果是錯誤解釋,你不能真正做任何事情,因爲很多字節在Windows-1255中沒有任何表示,並且沒有將其寫入字符串。

如果不是的話,你可以完全恢復原來的預期的消息:

new String(str.getBytes("Windows-1255"), "UTF-8"); 

*這其實是錯誤的Java允許未成代理人在其字符串存在擺在首位因爲它不是有效的UTF-16

+0

Ac通過幾乎所有處理'char'或'Character'的方法,'String'確實向最終用戶公開了UTF-16編碼的事實。諸如'charAt'等方法,任何需要索引或長度的方法等,都暴露了「String」代碼單元爲UTF-16的事實。這很不幸,可能是UCS2擴展爲UTF-16後,在Java中的這種行爲已經正式化之後的結果。如果UCS2沒有被取代,那麼API將是乾淨的,不會暴露代理等。 – BeeOnRope

+0

@BeeOnRope是的,但只有在很少使用的輔助平面上纔會顯現。它仍然可以正常使用BMP,並且沒有不成對的代理(請參閱答案中的腳註),這通常是99%的情況。 – Esailija

+0

當然,但我認爲你編寫的代碼將API視爲實際情況,並且涵蓋了100%的情況,而不是99%的情況,並且交叉手指指出沒有任何BMP字符出現。忽略它就像說你可以忽略UI中的RTL文本,夏令時,整數溢出等等,因爲它不會發生超過1%的時間。 字符串,從根本上呈現一個UTF-16 API。大多數情況下,你可以把它看作Unicode並放棄它,但我絕對不會這樣寫代碼,我絕不會聲明「它從用戶的角度來看沒有任何編碼」 。 – BeeOnRope