我正在将Java中的double值写入如下文件中,
byte[] bytes = new byte[8];
//Double d = new Double(4);
double d =1000;
ByteBuffer.wrap(bytes).putDouble(d);
File test = new File(FILE_PATH+"readme.bin");
test.createNewFile();
FileOutputStream ostream = new FileOutputStream(test);
ostream.write(bytes);
ostream.close();
我可以用Java代码读回来,但是当用C代码检索它时,我得到的值为0.000000
。我的C代码如下,
FILE *file_ptr;
file_ptr = fopen(file_absolute,"rb");
if (!file_ptr)
{
printf("Unable to open file!");
return 1;
}
char bytes[8];
fread(&bytes, 8, 1, file_ptr);
double d = *((double*)bytes);
printf("%f",d);
我在这里遗漏了什么? C和Java代码都在同一系统上运行。
答案 0 :(得分:0)
Java代码以与C期望相反的顺序输出字节。
所以你需要反转字节顺序。以下内容适用于标准的little-endian操作系统:
#include <stdio.h>
void main() {
FILE *file_ptr;
unsigned char bytes[sizeof(double)];
union {
double d;
unsigned char bytes[sizeof(double)];
} u;
int c;
file_ptr = fopen("float.bin","rb");
fread(bytes,sizeof(double),1,file_ptr);
for (c=0; c<sizeof(double); c++)
u.bytes[c]=bytes[sizeof(double)-1-c];
printf("%f\n", u.d);
}
只要目标系统对于我见过的任何标准系统和C编译器都是小端,这都可以。
如果要使代码更具可移植性,可以在编译时(使用宏,请参阅https://sourceforge.net/p/predef/wiki/Endianness/)或在运行时检测C代码的字节顺序。有一些不太常见的系统,特别是基于ARM和MIPS的系统,它们通常是大端的,并且这里不需要转换。无论底层系统如何,Java总是会产生大端输出,所以只有C代码需要是有条件的。
对于非常便携的版本,您可以使用宏检测字节顺序,或者在运行时,两个选项都在给定的链接中进行解释。如果您只是想在Windows上运行此代码,或者PC运行Linux,并且不关心可移植性,那么您可以使用上面的代码。
答案 1 :(得分:-1)
byte[] bytes = new byte[8];
//Double d = new Double(4);
double d =1000;
ByteBuffer.wrap(bytes).putDouble(d);
File test = new File(FILE_PATH+"readme.bin");
test.createNewFile();
FileOutputStream ostream = new FileOutputStream(test);
ostream.write(bytes);
ostream.close();
你不需要这一切。您可以在不到一半的代码中执行相同的操作:
DataOutputStream dos = new DataOutputStream(new FileOutputStream(test));
dos.writeDouble(1000);
dos.close();
具体来说,File.createNewFile()
调用是对时间和空间的毫无意义的浪费,而ByteBuffers
和字节数组的所有混乱都可以通过DataOutputStream.
但是,您遇到的问题是您的硬件C double
显然与您的Java double
写入文件的格式不同。请注意,与您提出的一些评论相反,这确实是可能的,因为C不必遵守IEEE-754的位格式或字节顺序。
有关详细信息,请参阅here。