最近研究微软的算法试题,有一道题目是IP防火墙匹配相关的,计算的时候需要将IP地址转换成32位的二进制。这里给出一个自己写的方法。
Java
public String ip2BinStr(String ip) {
String[] arr = ip.split("\.");
String rs = "";
for (String str : arr) {
String s = Integer.toBinaryString(Integer.parseInt(str));
if (s.length() < 8) {
int diff = 8-s.length();
for (int i = 0; i < diff; i++) {
s = "0" + s;
}
}
rs += s;
}
return rs;
}
这里int转化为二进制String的时候无法指定长度,导致还要进行前面补0的操作。写的过程中将Java中内置类型的toBinaryString()方法学习了下,这里写个笔记。
直接在源码上添加注释,在Integer类中,有方法如下
```Java```
public static String toBinaryString(int i) {
return toUnsignedString0(i, 1);
}
/**
* 将一个整数val变为无符号表示, shift表示进制以2为底的对数,比如,
* 1代表转成二进制,3代表8进制,4代表16进制。
*/
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
// Integer.SIZE=32,
// Integer.numberOfLeadingZeros返回整数的二进制表示左边有多少个连续的0,比如1是31个,2是30个
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
//chars是获取转换后的字符串长度,我还不造为什么是这么算。。。
int chars = Math.max(((mag + (shift - 1)) / shift), 1);
char[] buf = new char[chars];
//调用下面的那个函数填充buf
formatUnsignedInt(val, shift, buf, 0, chars);
// 调用String构造函数将char数组转换成String,看了String源码,发现这个true代表是否共享缓存的值吧。暂时不支持设置为false。。。
return new String(buf, true);
}
/**
* 将val(视作无符号的类型)格式化到char数组buf中
* offset 表示从buf的offset开始填充
* len 表示一共写多少个char
* 返回最低位,调用的时候并没有用到返回值
*/
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
int charPos = len;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[offset + --charPos] = Integer.digits[val & mask];
val >>>= shift;
} while (val != 0 && charPos > 0);
return charPos;
}