本文节选自《Netkiller Java 手札》
Netkiller Java 手札
Mr. Neo Chan, 陈景峯(BG7NYT)
版权声明
转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。
1.10.12. 二进制文件操作大全
1.10.12.1. 理解二进制文件
我们运行下面一段程序,向文件 netkiller.bin 中写入一个整形数值 1 ,然后观察文件变化
String filename = "netkiller.bin";
DataOutputStream out = new DataOutputStream(new FileOutputStream(filename));
out.writeInt(1);
out.close();
打开终端,使用 xxd 命令查看二进制文件
neo@MacBook-Pro ~/workspace/netkiller % xxd -b netkiller.bin
00000000: 00000000 00000000 00000000 00000001 ....
可以看到一串二进制 00000000 00000000 00000000 00000001,运行下面程序可以讲二进制转换为十进制,注意替换掉空格。
int n = Integer.valueOf("00000000 00000000 00000000 00000001".replaceAll(" ", ""), 2);
System.out.println(n);
运行结果是 1 ,为什前面那么多 0 呢?请运行下面一段程序
String filename = "netkiller.bin";
DataOutputStream out = new DataOutputStream(new FileOutputStream(filename));
out.writeInt(Integer.MAX_VALUE);
out.close();
现在观察结果
neo@MacBook-Pro ~/workspace/netkiller % xxd -b netkiller.bin
00000000: 01111111 11111111 11111111 11111111 ....
int n = Integer.valueOf("01111111 11111111 11111111 11111111".replaceAll(" ", ""), 2);
System.out.println(n);
输出结果是 2147483647, 这是 int 得最大值,2147483647 + 1 会怎么样呢?
String filename = "netkiller.bin";
DataOutputStream out = new DataOutputStream(new FileOutputStream(filename));
out.writeInt(Integer.MAX_VALUE + 1);
out.close();
System.out.println(Integer.MAX_VALUE + 1);
输出结果是 -2147483648,正确应该是 2147483648 这就是整形溢出。整形变量得二进制表示方法是4个字节长度32位 00000000 00000000 00000000 00000000 到 01111111 11111111 11111111 11111111 , 其中第一位0表示正数1表示负数。
neo@MacBook-Pro ~/workspace/netkiller % xxd -b netkiller.bin
00000000: 10000000 00000000 00000000 00000000 ....
整形溢出演示,超出整形范围怎么办? 使用 Long 型。
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MAX_VALUE + 1);
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MIN_VALUE - 1);
输出结果如下:
2147483647
-2147483648
-2147483648
2147483647
负数演示
String filename = "netkiller.bin";
DataOutputStream out = new DataOutputStream(new FileOutputStream(filename));
out.writeInt(-1);
out.writeInt(Integer.MAX_VALUE + 1);
out.close();
-1 得结果是 11111111 11111111 11111111 11111111
neo@MacBook-Pro ~/workspace/netkiller % xxd -b netkiller.bin
00000000: 11111111 11111111 11111111 11111111 ....
现在我们存储两个整形数值
String filename = "netkiller.bin";
DataOutputStream out = new DataOutputStream(new FileOutputStream(filename));
out.writeInt(1);
out.writeInt(-1);
out.close();
很清楚的看到里面有两个数值,1 和 -1
neo@MacBook-Pro ~/workspace/netkiller % xxd -c 4 -b netkiller.bin
00000000: 00000000 00000000 00000000 00000001 ....
00000004: 11111111 11111111 11111111 11111111 ....
读取二进制文件中的 int 数据
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
try {
int i = in.readInt();
System.out.println(i);
} catch (EOFException e) {
e.printStackTrace();
}
1.10.12.2. byte 类型
String filename = "netkiller.bin";
DataOutputStream out = new DataOutputStream(new FileOutputStream(filename));
out.writeByte(1);
out.close();
byte 只占用一个字节8位
neo@MacBook-Pro ~/workspace/netkiller % xxd -c 4 -b netkiller.bin
00000000: 00000001
如果写入 -1 结果是,由此得出 第一位 0 是正数,1 是负数,可以得出他的取值范围 -128 ~ 127。超出范围也会溢出。
neo@MacBook-Pro ~/workspace/netkiller % xxd -c 4 -b netkiller.bin
00000000: 11111111
常常写入最小值与最大值
String filename = "netkiller.bin";
DataOutputStream out = new DataOutputStream(new FileOutputStream(filename));
out.writeByte(Byte.MIN_VALUE);
out.writeByte(Byte.MAX_VALUE);
out.close();
运行结果