一起来看看Java中的“小剪刀”,位移运算 &0xFF 的深度解
2021-09-07 本文已影响0人
攻城狮Chova
Java位移操作
DataOutputStream
- 位于java.io.FilterOutputStream.DataOutputStream
- 与机器无关地写入各种类型的数据以及String对象的二进制形式,从高位开始写
- 任何机器上任何DataInputStream都能够读取这些写入的数据
- 所有的方法都以write开头.比如writeByte(), writeFloat()
PrintStream
- 位于java.io.FilterOutputStream.PrintStream
- 最初的目的是为了以可视化格式打印所有的基本数据类型以及String对象
- 和DataOutputStream不同的是: PrintStream目的是将数据元素置入 "流" 中,使得DataInputStream能够可移植地重构这些数据元素
二进制写入
字符串写成二进制
- 字符串本质是char的序列,也就是char[]
- 只要遍历写入每一个char, 就完成了写一个字符串的功能
char写成二进制
- 英语字母有ASCII码,可以将每个字符转换成对应的数字
-
Unicode码表: 字符和编码之间的映射,使用2个字节表示所有字符
- Unicode字符编码标准是固定长度的字符编码方案,包含世界上几乎所有现用语言的字符
-
Unicode根据要编码的数据类型使用两种编码格式:
-
16位:
- 默认编码格式为16位.即每个字符是16位(2个字节宽度)
- 通常显示为U+hhhh. 其中hhhh是字符的16进制代码点
- 8位
-
16位:
-
Unicode标准提供了一种扩展机制,允许编码一百多万个字符:
- 使用一对高位和低位代用字符来对扩展字符或补充字符进行编码
- 第一个高位代用字符: 具有U+D800和U+DBFF之间的值
- 第二个低位代用字符: 具有U+DC00和U+DFFF之间的值
writeChar源码
- 所以每一个char就是一个0-65535之间的数字
- DataOutputStream.writeChar源码:
public final void writeChar(String s) throws IOException {
int len = s.length();
for (int i = 0; i < len; i++) {
int v = s.charAt(i);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
}
incCount(len * 2);
}
writeShort源码
- 与writeChar相比 ,writeShort不需要遍历一遍string
- DataOutputStream.writeShort源码:
public final void writeShort(int v) {
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(2);
}
0xFF
-
二进制写入的问题:
- 为什么要用无符号右移?
- & 0xFF不会使得数的大小改变,为什么还要使用 & 0xFF ?
- 0xFF是16进制的255,也就是二进制的1111
- &是AND与操作,同时为1才为1,否则为0
位移运算
- 左移: <<. 右补0
-
有符号右移: >>. 左补符号位
- 如果符号位为1则左补1
- 如果符号位为0则左补0
- 无符号右移: >>>. 左补0
二进制写入原理
- 二进制写入的方式: 先取高8位写入,再写入低8位
-
示例: 写入的short字符对应的unicode码为3
- 先得到3的原码的高8位:
- 0000,0000,0000,0011 >>> 8得到0000,0000,0000,0000
- 然后再 & 0xFF得到最终结果0000,0000
- 再得到3的原码的低8位:
- 0000,0000,0000,0011 >>> 0得到0000,0000,0000,0011
- 然后再 & 0xFF得到最终结果0000,0011
- 先得到3的原码的高8位:
总结
- & 0xFF就相当于计算机中的剪刀,当'&'操作符两边数的bit位数相同时不改变数的大小,只是转么截出一个字节8bit的长度
- 同理 : & 0x0F可以得到4bit的长度