2013-03-16 46 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