2013-03-16 45 views
2

我的Android應用程序檢索SHOUTcast元數據並顯示它。我有和非英文字符集問題。基本上,元數據顯示爲亂碼。我將如何執行字符編碼檢測並正確顯示文本?對不起,如果這是一個不平凡的問題,我不太熟悉這個話題。Android中的字符集檢測

有問題的數據流是:http://skully.hopto.org:8000

+0

這取決於數據的來源。對於你的鏈接,你可以打開頁面的HTML代碼,你會看到''。這意味着編碼是Windows-1252,如果您僅使用此站點,則可以對此編碼名稱進行硬編碼並始終使用它。 – vorrtex 2013-03-16 09:56:21

回答

4

由於vorrtex在他的評論中指出的上述情況,如果您的數據來源,以及形成的HTML代碼,你可以從<meta content="...">標籤知道它的編碼,這是最好的情況。您可以將此轉換到Android(或其他Java實現)字符串代碼,如:

// assume you have your input data as byte array buf, and encoding 
// something like "windows-1252", "UTF-8" or whatever 
String str = new String(buf, encoding); 
// now your string will display correctly 

如果你不知道的編碼 - 你收到你的數據在未知格式的原始文本 - 你仍然可以嘗試算法猜測它,使用統計語言模型。我剛剛找到了ICU - 國際組件爲IBM項目,自由開放源碼許可(商業用途OK),在http://site.icu-project.org/

它們提供Java和C++庫。我剛剛添加了他們的Java JAR版本。 51.2到我的Android項目,它的工作就像一個魅力。我以前從文本文件中識別字符編碼的代碼是:

public static String readFileAsStringGuessEncoding(String filePath) 
{ 
    String s = null; 
    try { 
     File file = new File(filePath); 
     byte [] fileData = new byte[(int)file.length()]; 
     DataInputStream dis = new DataInputStream(new FileInputStream(file)); 
     dis.readFully(fileData); 
     dis.close(); 

     CharsetMatch match = new CharsetDetector().setText(fileData).detect(); 

     if (match != null) try { 
      Lt.d("For file: " + filePath + " guessed enc: " + match.getName() + " conf: " + match.getConfidence()); 
      s = new String(fileData, match.getName()); 
     } catch (UnsupportedEncodingException ue) { 
      s = null; 
     } 
     if (s == null) 
      s = new String(fileData); 
    } catch (Exception e) { 
     Lt.e("Exception in readFileAsStringGuessEncoding(): " + e); 
     e.printStackTrace(); 
    } 
    return s; 
} 

Lt.dLt.e以上只是我對Log.d(TAG快捷鍵,「嗒嗒......」 )。在我能想到的所有測試文件上工作得很好。我只關心APK文件的大小 - icu4j-51_2.jar的長度超過了9 MB,在添加之前我的整個包只有2.5 MB。但是很容易將CharsetDetector和它的依賴關係隔離開來,所以我最終添加了不超過50kB的內存。我需要複製到從ICU來源我的項目的Java類都在覈心/ src目錄/ COM/IBM/ICU /文本目錄,分別爲:

CharsetDetector 
CharsetMatch 
CharsetRecog_2022 
CharsetRecog_mbcs 
CharsetRecog_sbcs 
CharsetRecog_Unicode 
CharsetRecog_UTF8 
CharsetRecognizer 

此外,在CharsetRecog_sbcs.java有一個保護「ArabicShaping如;'成員,它想要拉更多的課程,但事實證明,對於字符集識別它不是必需的,所以我評論了它。就這樣。希望能幫助到你。

Greg

+0

但我必須使用輸入流才能從元標記獲取該值。同時,我應該將尚未知道的編碼值傳遞給inputstreamreader。然後由於編碼錯誤,字節信息完全丟失。即使我以後可以從meta標籤中獲得正確的編碼,我該如何將其轉換回正確的編碼? – 2015-11-26 02:47:11

+0

上面討論的使用ICU庫的方法在字節數組上工作,並且不需要先轉換爲字符串。或者有創意,例如將字節數組視爲ASCII字符串來搜索標籤,因爲它們都是ASCII字符。我實際上這樣做,但在JNI C++代碼。 – gregko 2015-11-27 13:27:02

+0

感謝關於ICU庫的漂亮小貼士。似乎ArabicShaping成員在他們的Java庫的最新版本中不再產生任何問題。 BTW:指出ICU庫中的一個子集將包含在Android N中。 – moster67 2016-04-03 21:57:15