java中的位运算
以下是一本书中的代码,不明白为什么要使用位运行和与运算,求解析,谢谢。public class LengthFramer implements Framer {
public static final int MAXMESSAGELENGTH = 65535;
public static final int BYTEMASK = 0xff;
public static final int SHORTMASK = 0xffff;
public static final int BYTESHIFT = 8;
private DataInputStream in; // wrapper for data I/O
public LengthFramer(InputStream in) throws IOException {
this.in = new DataInputStream(in);
}
public void frameMsg(byte[] message, OutputStream out) throws IOException {
if (message.length > MAXMESSAGELENGTH) {
throw new IOException("message too long");
}
// write length prefix
out.write((message.length >> BYTESHIFT) & BYTEMASK);
out.write(message.length & BYTEMASK);
// write message
out.write(message);
out.flush();
}
public byte[] nextMsg() throws IOException {
int length;
try {
length = in.readUnsignedShort(); // read 2 bytes
} catch (EOFException e) { // no (or 1 byte) message
return null;
}
// 0 <= length <= 65535
byte[] msg = new byte[length];
in.readFully(msg); // if exception, it's a framing error.
return msg;
}
} --------------------编程问答-------------------- 是要转化成16进制么~ --------------------编程问答-------------------- 由于String.length>=0,再加上限制条件:String.length<=65535(学过C的大都能一眼看出这个数是2^16-1)
等于是把字符串的长度限制成一个只有16位的无称号整数。
而红色的部分分别是取length的高8位与低8位。 --------------------编程问答-------------------- out.write((message.length >> BYTESHIFT) & BYTEMASK);
out.write(message.length & BYTEMASK);
右移八位要干啥???? --------------------编程问答--------------------
。。。有什么意义捏。。。。 --------------------编程问答--------------------
这个是往流(套接字)中写入数据,为什么不直接写入呢? --------------------编程问答-------------------- out.write((message.length >> BYTESHIFT) & BYTEMASK);//先写高位俩字节
out.write(message.length & BYTEMASK);//再写低位俩字节
这样读取的时候先读俩字节×256+后俩字节=总长度了
java输出流写int的时候只写低位俩字节,所以out.write(65534)和out.write(254) 结果是一样的
即16进制的都是FE --------------------编程问答--------------------
在下不熟悉Framer接口,本来是想来混个几分把Java板块也升到2级的。
但这里既然问到了,我就提点不成熟的看法吧。
这个类的功能粗略分析了一下,貌似是进行数据包的筛选的。它会把长度过长(65535为上限)的包抛掉。
至于红色部分的功能,这涉及到数据存储方式的问题。计算机内存存储数据有两种模式:大端模式(Big-Endian)和小端模式(Little-Endian),Big-Endian的内存地址分配是从大到小的(例如2001地址是在2000前面),而Little-Endian则与之相反(中国用得比较多的x86系列计算机都是Little-Endian的,所以接触到Big-Endian的可能较少)。
例如:一整数0x0d0f,存放地址为2000,
在B-Endian下,地址2000存放的数据是0d,而L-Endian下,地址2000存放的数据是0f。
用write打散成字节流后,B-Endian系统传输的顺序是0d->0f,L-Endian系统传输的则是0f->0d。
而在接收端,readUnsignedShort函数不知道发送方是B-Endian还是L-Endian,它统一按照B-Endian的方式处理(这个推论是从上面的代码分析出来的)。
因此,发送方要用位运算的方法来保证第一个传过去的字节是数据的高8位。
补充:Java , Java SE