前言
最近在实现一个socket通信的功能,消息头第一个字段是整个消息长度,用四字节表示。非常简单的一个功能,我却把自己绕晕了,归根结底还是基础不牢,懊恼不已。
与我交互的网元说该字段要以16进制的类似下面的形式发送,比如长度356,如下所示:
00 00 01 64
于是我便在十六进制byte上较上劲了。int分十进制、十六进制,但是它们底层都是“1”“0”的串,所以转成byte后都是一样的,没有什么十进制十六进制的分别。比如下面的代码的结果是true。
byte a = (byte)0x23;
byte b = 35;
System.out.println(a == b);
所以我根本无需纠结int型转成byte型之后的表示形式。直接将int型的长度转成byte数组发送即可。
目录
String 转byte[]
int 转byte[]
String 转byte[]
可以直接调用String的getBytes方法,或者指定特定的charset进行转换。
public byte[] getBytes() {
return StringCoding.encode(value, offset, count);
}
public byte[] getBytes(Charset charset) {
if (charset == null) throw new NullPointerException();
return StringCoding.encode(charset, value, offset, count);
}
int 转byte[]
参考 DataOutputStream的writeInt方法可以实现一个int转byte数组的方法
public final void writeInt(int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}
/**
* int到byte[]
* @param i
* @return
*/
public static byte[] intToByteArray(int i) {
byte[] result = new byte[4];
//由高位到低位
result[0] = (byte)((i >> 24) & 0xFF);
result[1] = (byte)((i >> 16) & 0xFF);
result[2] = (byte)((i >> 8) & 0xFF);
result[3] = (byte)(i & 0xFF);
return result;
}
为什么要& 0xFF,查询了一下资料,得到解释如下:
java的二进制采用的是补码形式
⑴一个数为正,则它的原码、反码、补码相同
⑵一个数为负,刚符号位为1,其余各位是对原码取反,然后整个数加1
因为补码存在,所以右移运算后要与0xff相与运算