我有一个Java程序在外部进程中运行msinfo32.exe(系统信息),然后读取由msinfo32.exe生成的文件内容。 当Java程序将文件内容加载到String中时,String字符是不可读的。 为了使string可读,我必须使用String(byte [] bytes,String charsetName)创buildString,并将charsetName设置为UTF-16。 但是,在Windows2003的一个实例上运行时,只有UTF-16LE(little endian)会产生可打印的string。
我怎样才能提前知道使用哪种字符编码?
此外,任何关于这个主题的背景信息将不胜感激。
某些Microsoft应用程序使用字节顺序标记来指示Unicode文件及其字节顺序。 我可以在我的Windows XP机器上看到导出的.NFO文件以0xFFFE开头,所以它是小端的。
FF FE 3C 00 3F 00 78 00 6D 00 6C 00 20 00 76 00 __<_?_x_m_l_ _v_ 65 00 72 00 73 00 69 00 6F 00 6E 00 3D 00 22 00 e_r_s_i_o_n_=_"_ 31 00 2E 00 30 00 22 00 3F 00 3E 00 0D 00 0A 00 1_._0_"_?_>_____ 3C 00 4D 00 73 00 49 00 6E 00 66 00 6F 00 3E 00 <_M_s_I_n_f_o_>_ 0D 00 0A 00 3C 00 4D 00 65 00 74 00 61 00 64 00 ____<_M_e_t_a_d_
此外,我建议您切换到使用Reader实现,而不是解码文件的字符串构造函数; 这有助于避免在读取半个字符时出现问题,因为它被截断,因为它位于字节数组的末尾。
你可以尝试使用库来猜测编码,例如我曾经使用过这个解决方案 。
你不能真正知道使用了什么字符编码(除非你创建了创建你正在处理的输出的工具)。 您可以尝试检测预定义的编码列表,并选择不会导致任何解码错误的编码,但取决于可能匹配很多不同编码的输入。
如果您事先不知道字符编码,并且在各种平台上有所不同,那么您需要以某种方式分析字节数组以尝试猜测它。 有一些检测算法可用,但它可能是一个矫枉过正的应用程序。
你可以调整你的应用程序产生一个已知的输出? 没有必要成为一个完整的行,只有第一个字符会做。 如果是的话,那么你可以比较产生的字节数组与预期的各种编码,并进行检测。 对于简单字符串,UTF8,UTF-16大小端的字节数组将是不同的事件。
它应该工作的方式是,如果有人给你一个文件,说它是UTF-16,他们希望你检查前两个字节(BOM),以找出它是大端还是小端。 但是如果他们告诉你编码是UTF-16LE ,就意味着没有BOM; 你不需要它,因为他们已经告诉你,字节顺序是小端的。 Java精确地遵循这些规则,因为没有其他人这样做,所以这是一个真正的实用程序。
现代Windows操作系统的本地字符编码是UTF-16,小端。 不幸的是,个别程序在字节顺序标记方面似乎并不一致。 而且不能一直使用UTF-16LE,因为如果BOM存在,它将作为垃圾字符传递。 提前知道是否使用UTF-16或UTF-16LE的唯一方法是检查前两个字节,如McDowell所述。