2个在Java中将Byte []数组转换为String的示例
將字節數組轉換為String似乎很容易,但是很難做到正確。 每當字節轉換為String或char時,許多程序員都會犯忽略字符編碼的錯誤,反之亦然。 作為程序員,我們都知道計算機只能理解二進制數據,即0和1。我們看到和使用的所有內容,例如圖像,文本文件,電影或任何其他多媒體,都以字節形式存儲,但更重要的是是將字節編碼或解碼為字符的過程。 數據轉換是任何編程面試中的重要主題,并且由于字符編碼的棘手性,該問題是Java面試中最受歡迎的String Interview問題之一 。 從輸入源(例如XML文件,HTTP請求,網絡端口或數據庫)讀取字符串時,必須注意編碼它們的字符編碼(例如UTF-8,UTF-16和ISO 8859-1)。 如果在將字節轉換為String時不使用相同的字符編碼,則最終會導致String損壞,其中可能包含完全不正確的值。 您可能已經看到?,在將byte []轉換為String之后的方括號,是由于您當前的字符編碼不支持這些值,而只是顯示了一些垃圾值。
我試圖理解為什么程序經常會犯字符編碼錯誤,而我的研究和經驗表明,這可能是由于兩個原因,首先是國際化和字符編碼處理不充分,其次是ASCII字符受支持。幾乎所有流行的編碼方案都具有相同的值。 由于我們主要處理UTF-8,Cp1252和Windows-1252之類的編碼,即使您使用不同的編碼方案,它們也會顯示ASCII字符(主要是字母和數字)而不會失敗。 當您的文本包含特殊字符(例如'é')時 ,真正的問題就來了,這在法語名稱中經常使用。 如果平臺的字符編碼無法識別該字符,那么您將看到一個不同的字符或某種垃圾,并且可悲的是,直到您的手被燙傷為止,您不太可能對字符編碼保持謹慎。 在Java中,事情有點棘手,因為默認情況下,許多IO類(例如InputStreamReader)使用平臺的字符編碼。 這意味著,如果在不同的計算機上運行程序,則由于該計算機上使用的字符編碼不同,您可能會獲得不同的輸出。 在本文中,我們將學習如何通過使用JDK API以及Guava和Apache Commons的幫助, 在Java中將byte []轉換為String 。
在Java中,有多種將字節數組更改為String的方法,您可以使用JDK中的方法,也可以使用開放源代碼的補充API,例如Apache Commons和Google Guava。 這些API提供了至少兩組方法來創建String形式的字節數組。 一種使用默認平臺編碼,另一種使用字符編碼。 您應該始終使用后面的一種,不要依賴平臺編碼。 我知道,可能是相同的,或者到目前為止您可能還沒有遇到任何問題,但是安全起來總比對不起好。 正如我在上一篇關于將字節數組打印為十六進制字符串的文章中所指出的那樣,這也是在將字節轉換為任何編程語言的字符時指定字符編碼的最佳實踐之一。 您的字節數組可能包含不可打印的ASCII字符。 首先讓我們看看JDK將byte []轉換為String的方式:
這是將字節轉換為String的正確方法,前提是您可以確定字節是以您使用的字符編碼進行編碼的。
為了正確地將這些字節數組轉換為String,您必須首先通過讀取元數據來發現正確的字符編碼,例如Content-Type,<?xml encoding =”…”>等,具體取決于所讀取數據的格式/協議。 這是我建議使用XML解析器(例如SAX或DOM解析器)讀取XML文件的原因之一,它們自己負責字符編碼。
一些程序員還建議使用Charset over String來指定字符編碼,例如,代替“ UTF-8”使用StandardCharsets.UTF_8主要是為了避免在最壞的情況下出現UnsupportedEncodingException。 保證所有Java平臺實現都支持六個標準的Charset實現。 您可以使用它們來代替在String中指定編碼方案。 簡而言之,始終首選使用StandardCharsets.ISO_8859_1而不是“ ISO_8859_1”,如下所示:
String str = IOUtils.toString(fis,StandardCharsets.UTF_8);Java平臺支持的其他標準字符集是:
如果您正在從輸入流中讀取字節,則還可以查看我之前的文章,了解有關在Java中將InputStream轉換為String的5種方法 。
原始XML
這是我們的示例XML代碼段,以演示使用默認字符編碼的問題。 該文件包含字母'é' ,由于默認字符編碼為Cp1252 ,因此無法在Eclipse中正確顯示。
xml version="1.0" encoding="UTF-8"?> <banks><bank><name>Industrial & Commercial Bank of China </name><headquarters> Beijing , China</headquarters></bank><bank><name>Crédit Agricole SA</name><headquarters>Montrouge, France</headquarters></bank><bank><name>Société Générale</name><headquarters>Paris, ?le-de-France, France</headquarters></bank> </banks>并且,當您將字節數組轉換為String而不指定字符編碼時會發生這種情況,例如:
String str = new String(filedata);這將使用平臺的默認字符編碼,在這種情況下為Cp1252 ,因為我們正在Eclipse IDE中運行此程序。 您會看到字母“é”顯示不正確。
xml version="1.0" encoding="UTF-8"?> <banks><bank><name>Industrial & Commercial Bank of China </name><headquarters> Beijing , China</headquarters></bank><bank><name>Cr??dit Agricole SA</name><headquarters>Montrouge, France</headquarters></bank><bank><name>Soci??t?? G??n??rale</name><headquarters>Paris, ??le-de-France, France</headquarters></bank> </banks>要解決此問題,請在從字節數組創建String時指定字符編碼,例如
String str = new String(filedata, "UTF-8");順便說一句,讓我說清楚,即使我已經在這里使用InputStream讀取XML文件,這也不是一個好習慣,實際上,這是個壞習慣。 您應該始終使用正確的XML解析器來讀取XML文檔。 如果您不知道如何操作,請查看本教程 。 由于此示例主要是為了向您展示字符編碼為何重要,因此我選擇了一個易于使用且看起來更實用的示例。
這是我們的示例程序,以說明為什么依賴默認字符編碼是一個壞主意,以及為什么在Java中將字節數組轉換為String時必須使用字符編碼。 在此程序中,我們使用Apache Commons IOUtils類將文件直接讀取到字節數組中。 它負責打開/關閉輸入流,因此您不必擔心泄漏文件描述符。 現在,如何使用該數組創建String是關鍵。 如果提供正確的字符編碼,則將獲得正確的輸出,否則將獲得幾乎正確但不正確的輸出。
永遠記住,在將字節數組轉換為String的同時使用字符編碼不是最佳實踐,而是強制性的事情。 無論編程語言如何,都應始終使用它。 順便說一句,您可以注意以下幾點,這將幫助您避免幾個討厭的問題:
- 使用源代碼中的字符編碼,例如HTML文件中的Content-Type或<?xml encoding =”…”>。
- 使用XML解析器來解析XML文件,而不是查找字符編碼并通過InputStream讀取它,有些事情最好僅用于演示代碼。
- 首選字符集常量,例如StandardCharsets.UTF_16而不是字符串“ UTF-16”
- 從不依賴平臺的默認編碼方案
當您將字符數據轉換為字節時,也應應用此規則,例如,使用String.getBytes()方法將String轉換為字節數組。 在這種情況下,它將使用平臺的默認字符編碼,而不是使用應采用字符編碼的重載版本。
這就是如何在Java中將字節數組轉換為String的全部內容。 如您所見,Java API(特別是java.lang.String類)提供了方法和構造函數,這些方法和構造函數采用byte []并返回String(反之亦然),但是默認情況下它們依賴于平臺的字符編碼,這可能不正確,如果字節數組是根據XML文件,HTTP請求數據或網絡協議創建的。 您應該始終從源代碼本身獲得正確的編碼。 如果您想了解更多關于每個程序員都應該知道的字符串是什么,你可以檢出該文章。
翻譯自: https://www.javacodegeeks.com/2014/09/2-examples-to-convert-byte-array-to-string-in-java.html
總結
以上是生活随笔為你收集整理的2个在Java中将Byte []数组转换为String的示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样修改家里路由器的密码友家路由器密码如
- 下一篇: Java并发教程–锁定:内在锁