snmp4j 中的中文字符输出问题, 不在于解码,而在于输出。
在使用snmp4j 通过 ip 和 OID来获取 snmp代理的 网络接口描述时, 在snmp4j-1.11.1上测试,当遇到中文或者编码值大于 0x80 的字符时,就会直接以十六机制数给出,并且给出的十六机制数是通过与 0xff 做 & 运算的值,比如说: response中包含字符的十六机制表示是:
0xffffffda(32位), 就会输出 0Xda, 其实查看snmp4j的源代码,snmp send request的同时获取的response的 PDU 都会通过 BER 来解码(主要研究了一下 decodeString), 可以跟中response 给出的 PDUInputstream 的值,通过输出byte数组(如New String(Byte[]))输出都是正常的32位置和对应的正确的编码显示:
其实同snmp++ 一样,是在输出字符的时候,在
package org.snmp4j.smi 中包含的 class OctetString.java 在输出结果转换成字符窜的时候回调用
public String toString() {
if (isPrintable()) { // 见下面的 isPrintable() 方法
return new String(value);
}
return toHexString(); // Hex 输出
}
/* 如果想要输出中文,直接将 if 语句注释即可解决 */
/**
* Determines whether this octet string contains non ISO control characters
* only.
* @return
* false
if this octet string contains any ISO control
* characters as defined by Character.isISOControl(char)
* except if these ISO control characters are all whitespace characters
* as defined by Character.isWhitespace(char)
.
*/
public boolean isPrintable() {
for (int i=0; i char c = (char)value[i]; if ((Character.isISOControl(c) || ((value[i] & 0xFF) >= 0x80)) && (!Character.isWhitespace(c))) { // (value[i] & 0xFF) >= 0x80) return false; } } return true; } /* Source code 中可以查看到 toHexString 会调用到下面的toString方法,语句 value[i] & 0xFF 是输出结果为被截取的十六进制数的原因 */ public String toString(char separator, int radix) { int digits = (int)(Math.round((float)Math.log(256)/Math.log(radix))); StringBuffer buf = new StringBuffer(value.length*(digits+1)); for (int i=0; i if (i > 0) { buf.append(separator); } int v = (value[i] & 0xFF); String val = Integer.toString(v, radix); for (int j=0; j < digits - val.length(); j++) { buf.append('0'); } buf.append(val); } return buf.toString(); } 至于为什么snmp4j 的设计是出于什么目的要屏蔽掉对于 大于 0Xff 的字符的输出的原因 可能是因为 snmp 获取的信息大都是英文,如此可以节省输出时的空间,还是有其他原因,还不得而知,现在想的是这样的改变输出 其他 字符 会不会带来其他的副作用。