Java读取C写的float,int和字符数组
程序员文章站
2022-04-25 15:49:49
...
0.README
本文提到了在用Java读取C写的字节文件时,因为两种语言的不同而遇到一些不兼容问题,包括float
读取方式,int
读取方式,char[]
数组转字符串。
1.Java 读取C写的小端float
Intel主机中C写入的字节顺序是从低到高(左低到右高),而java.io.DataInputStream
读取的数据是从高到低(左高到右低) 。前者称为LITTLE-ENDIAN
(小字节序、低字节序),即低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。 后者对应的是:BIG-ENDIAN
(大字节序、高字节序)。
因此我们需要调整字节的读取顺序。下面的例子中使用java.nio.ByteBuffer
来处理。
// 读取C语言写的float
public static float readFloatFromC(DataInputStream dataInputStream){
byte[] bytes = new byte[Float.SIZE/8];
try {
dataInputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getFloat();
}
2.Java 读取C语言写的小端int
// read a integer from little-endian bytes
public static int readIntLe(byte[] bytes, int offset) {
return (bytes[offset] & 0xff) | (bytes[offset + 1] & 0xff) << 8
| (bytes[offset + 2] & 0xff) << 16 | (bytes[offset + 3] & 0xff) << 24;
}
3.Java 将C语言写的字符数组转换为String
首先,c语言的char
只有一个字节,而java的char
有2个字节,所以用java中的byte[]
来存放从字节流中读取的C语言写的char[]
;然后用byte[]
和字符集生成String
;最后去掉C语言中的字符数组结束符‘\0’
// c写的字符数组转化为String
public static String byteArrayToString(byte[] bytes){
String s = null;
try {
s = new String(bytes, "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return s.substring(0, s.indexOf(0));
}
4. Java 读取C++写的结构体文件
class PreSysSet
{
public:
int first;
int second;
int third;
bool fourth;
int fifth;
}
Java 在读取C++的结构体时,主要的问题是要考虑到C++结构体保存时的存储结构,有两个规则(详细解释将参考资料4):
- 结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
- 结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数
所以前4个i变量的偏移量分别是0、4、8、12,为了使结构体大小是int大小的整数倍,最后一个int变量在保存时会对齐偏移量,不是12 + 1 = 13,而是12 + 4 = 16,这样才能保证结构体大小为20。所以正确的 Java 读取方式如下:
static class PreSysSet {
int first;
int second;
int third;
boolean fourth;
int fifth;
PreSysSet(DataInputStream in) {
try {
first = FileUtil.readIntFromC(in);
second = FileUtil.readIntFromC(in);
third = FileUtil.readIntFromC(in);
fourth = in.readBoolean();
in.skipBytes(3); // 为了对齐,所以产生了空位
fifth = FileUtil.readIntFromC(in);
} catch (IOException e) {
e.printStackTrace();
}
}
}
参考文献
上一篇: float浮点类型保留两位小数
下一篇: float:left后,导航栏不左浮解决