我有一个Java程序在外部进程中运行msinfo32.exe(系统信息),然后读取msinfo32.exe生成的文件内容。当Java程序将文件内容加载到String中时,String字符是不可读的。要使String可读,我必须使用String(byte [] bytes,String charsetName)创建String,并将charsetName设置为UTF-16。但是,当在Windows2003的一个实例上运行时,只有UTF-16LE(小端)会产生可打印的字符串。
我怎样才能提前知道要使用哪种字符编码?
此外,我们将非常感谢有关此主题的任何背景信息。
答案 0 :(得分:5)
某些Microsoft应用程序使用byte-order mark来指示Unicode文件及其字节序。我可以在我的Windows XP机器上看到导出的.NFO文件以0xFFFE开头,所以它是little-endian。
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实现而不是String构造函数来解码文件;这有助于避免读取半个字符的问题,因为它被截断,因为它位于字节数组的末尾。
答案 1 :(得分:2)
您可以尝试使用库来猜测编码,例如我曾使用过this solution。
答案 2 :(得分:1)
你真的不知道使用了什么字符编码(除非你创建了创建你正在处理的输出的工具)。您可以尝试检测预定义编码列表,并选择不会导致任何解码错误的编码,但取决于可能与许多不同编码匹配的输入。
答案 3 :(得分:0)
如果您事先不知道字符编码,并且这在各种平台之间是不同的,那么您需要以某种方式分析字节数组以尝试猜测它。有一些检测算法可用,但它可能对你的应用程序来说太过分了。
您可以调整您的应用程序以产生已知输出吗?不需要是一个完整的行,只有第一个字符才能完成。如果是,那么您可以将生成的字节数组与各种编码中的预期进行比较并进行检测。对于简单的字符串,UTF8,UTF-16大字节和小字节的字节数组将是不同的事件。
答案 4 :(得分:0)
它的工作方式是,如果有人给你一个文件并说它是UTF-16,他们希望你检查前两个字节(BOM),看看它是big-endian还是little-endian。但如果他们告诉你编码是 UTF-16LE ,那就意味着没有BOM;你不需要它,因为他们已经告诉你字节顺序是little-endian。 Java精确地遵循这些规则,这是一个真正的pisser,因为没有其他人这样做。
现代Windows操作系统的本机字符编码是UTF-16,little-endian。不幸的是,在字节顺序标记方面,单个程序似乎并不一致。而且你不能一直使用UTF-16LE,因为如果BOM 那里,它将作为垃圾字符传递。提前知道是使用UTF-16还是UTF-16LE的唯一方法是检查前两个字节,正如McDowell所描述的那样。