最近和C语言的系统有交互,需要给对方传输二进制文件,但C语言的文件默认是小端,而Java作为网络应用程序,默认是大端
因此需要在写入二进制文件的时候修改一下写入字节的顺序。
先看看普通写入
FileOutputStream fos = new FileOutputStream("D:/temp/test.txt");
BufferedOutputStream bos=new BufferedOutputStream(fos);
DataOutputStream dos=new DataOutputStream(bos);
dos.writeShort(66);
dos.close();
bos.close();
fos.close();
用16进制编辑器打开文件可以看到内容为
00 42
然而C语言中的顺序是小端先行,即
42 00
查看DataOutputStream.writeShort源码,其实它也是将数值分解成8位二进制(1byte)写入
public final void writeShort(int v) throws IOException {
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(2);
}
故我们可以手动写入byte数组,将目标数值手动转化为一个byte数组,于是我们写一个方法
// 小端输出模式
public static byte[] short2Bytes(short a) {
return new byte[] {
(byte) (a & 0xFF),
(byte) ((a >> 8) & 0xFF)
};
}
修改调用,将最开始的
dos.writeShort(66);
改为
dos.write(short2Bytes((short)66));
输出文件就是小端先行了。
上面例子是写入short。int也是同理,写一个方法手动将int转byte数组
// 小端输出模式
public static byte[] int2Bytes(int a) {
return new byte[] {
(byte) (a & 0xFF),
(byte) ((a >> 8) & 0xFF),
(byte) ((a >> 16) & 0xFF),
(byte) ((a >> 24) & 0xFF)
};
}
调用的时候将
dos.writeInt(66);
改为
dos.write(int2Bytes(66));
至于long,按照规律,相信读者自己可以写出来。
最后附上完整demo代码
package smallend;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
public class SmallEndTest {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("D:/temp/test.txt");
BufferedOutputStream bos=new BufferedOutputStream(fos);
DataOutputStream dos=new DataOutputStream(bos);
dos.writeShort(66); // 00 42
dos.write(short2Bytes((short)66)); // 42 00
dos.writeInt(66); // 00 00 00 42
dos.write(int2Bytes(66)); // 42 00 00 00
dos.close();
bos.close();
fos.close();
}
// 小端输出模式
public static byte[] short2Bytes(short a) {
return new byte[] {
(byte) (a & 0xFF),
(byte) ((a >> 8) & 0xFF)
};
}
// 小端输出模式
public static byte[] int2Bytes(int a) {
return new byte[] {
(byte) (a & 0xFF),
(byte) ((a >> 8) & 0xFF),
(byte) ((a >> 16) & 0xFF),
(byte) ((a >> 24) & 0xFF)
};
}
}
吐槽一下:网上找了半天博客,方法内容一大堆,楞是不知道到底咋用【大概我领悟力太差】。最后还是自己弄出来了,特此记录一下。