Java获取网卡接口名称的乱码问题
大概文字编码处理得多了,连同事遇到这方面问题,都跑过来问余了。
今晚同事遇到获取网卡接口名称乱码,无论怎么转都无法解决。
果然最好的方法还是查看字符串的二进制内容,乱猜是无用的。
平台是日文正版xp
NetworkInterface的getDisplayName()方法返回值是String,那确定就是一个Unicode字符串了
直接打印这个名称,最后一个”-“之后的字符串都不正常
使用String的getBytes(“UTF-16”)方法取出字串的二进制内容,全部打印出来,前几个以及最后几个的值如下
-2 -1 0 73 // -> I 0 110 // -> n 0 116 // -> t 0 101 // -> e 0 108 // -> l ... ... ... 0 -125 0 80 0 -125 0 87
首两个字符是-2,-1,也即0xFE,0xFF,大尾的BOM(Java你到底有多变态),每个字符都是高位在前
ASCII部分的字符高位为0,毫无疑问开头的几个字符就是Intel
来看最后几个字符
去掉0之后,序列是-125 80 -125 87,也即0x83 0x50 0x83 0x57,酷似多字节编码
打开WinHex(D版UltraEdit是不能装的),新建一个四字节文件,多字节编码在文本中都是先高位后低位,
于是按顺序写入16进制值,保存为txt文件
用记事本打开txt,结果是”ケジ”(日文版xp)
还可以用Ansi2Unicode打开,选择其他编码查看转换结果,Shift-JIS是最正常的了
于是终于可以下结论,这个字符串的原始编码就是Shift-JIS,但被分开成一个个byte,高位填充0,暴力转换为Unicode字符串。
这样的字符串非常的不正常,难怪怎么转都不对了
还原方法:去掉头部的BOM,去掉所有的0,得到二进制数组,在new一个String的同时,指定这个二进制数组的编码是Shift-JIS
import java.io.UnsupportedEncodingException; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; public class hello { public static void main(String[] args) { System.out.println("日本語"); try { Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface ni = (NetworkInterface)interfaces.nextElement(); byte[] b = ni.getDisplayName().getBytes("UTF-16"); byte[] dst = new byte[b.length]; for (int i=0; i<dst.length; i++) { dst[i] = 0; } int k=0; for (int i=0; i<b.length; i++) { if ((b[i]!=0) && (b[i]!=-1) && (b[i]!=-2)) { dst[k] = b[i]; k++; } } String name = new String(dst, "Shift_JIS").trim(); System.out.println(b.length); System.out.println(ni.getDisplayName()); System.out.println(name); } } catch (SocketException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
猜测是JDK调用了win32 api,却没有处理返回来的字符串编码
同事说Win7平台上没有问题,不需要转换,可能是因为win7系统的api返回的是Unicode字符串
这个修正方法和平台相关,很不通用
评论