C/C++读取二进制文件中的float、double数据

关于float和double在计算机中的存储结构这里就不赘述了,一般主要是PC机法,用补码的方式存储,

不过这个跟我们用程序读取数据的关系不大,计算机自己知道怎么读。

由于Intel系列的CPU都采用小端序标准,即主机字节序与网络字节序相反,所以需要换一下顺序。

float read_float(istream& is)
{
	unsigned int value;
	is.read((char*)&value, 4);
	unsigned int idata1, idata2, idata3, idata4;
	idata1 = 255 & (value >> 24);
	idata2 = 255 & (value >> 16);
	idata3 = 255 & (value >> 8);
	idata4 = 255 & value;
	
	char str[9];
	sprintf(str, "%02x%02x%02x%02x", idata4, idata3, idata2, idata1);
	str[8] = 0;
	float a;
	sscanf(str, "%x", &a);
	return a;
}
这是通过移位的方式来达到最终的目的,也可以直接读到一个字符串里,再变换顺序输出


char re[5];
	re[4] = 0;
	is.read(re, 4);
	for (int i = 0; i < 2; i++)
	{
		char c = re[i];
		re[i] = re[3 - i];
		re[3 - i] = c;
	}
	float a = *(float*)re;
	return a;
 
  
 后面这种方法同样适用于double类型的数据读取,只不过4个字节变8个字节而已。 
  

但是第一种方法用来读取double读到的会是一个错误的结果,至于原因,我想是因为...

unsigned __int64 value;
	is.read((char*)&value, 8);

	unsigned __int8 idata1, idata2, idata3, idata4, idata5, idata6, idata7, idata8;
	idata1 = 255 & (value >> 56);
	idata2 = 255 & (value >> 48);
	idata3 = 255 & (value >> 40);
	idata4 = 255 & (value >> 32);
	idata5 = 255 & (value >> 24);
	idata6 = 255 & (value >> 16);
	idata7 = 255 & (value >> 8);
	idata8 = 255 & value;
	
	char str[17];
	str[16] = 0;

	sprintf(str, "%02x%02x%02x%02x%02x%02x%02x%02x", idata8, idata7, idata6, idata5,idata4, idata3, idata2, idata1);
	double a;
	sscanf(str, "%x", &a);
这里的字符串str有16个字节,目前C/C++里好像还没有16个字节的数据类型,我猜测可能是从16字节的字符串输出 到8个字节的数据的时候会出问题。

double read_double(istream& is)
{
	unsigned __int64 value;
is.read((char*)&value, 8);

unsigned __int64 idata1, idata2, idata3, idata4, idata5, idata6, idata7, idata8;
idata1 = 255 & (value >> 56);
idata2 = 255 & (value >> 48);
idata3 = 255 & (value >> 40);
idata4 = 255 & (value >> 32);
idata5 = 255 & (value >> 24);
idata6 = 255 & (value >> 16);
idata7 = 255 & (value >> 8);
idata8 = 255 & value;
value = (idata8 << 56) + (idata7 << 48) + (idata6 << 40) + (idata5 << 32)
+ (idata4 << 24) + (idata3 << 16) + (idata2 << 8) + idata1;
char str[9];
str[8] = 0;
double a;
memcpy(str, &value, 8);
memcpy(&a, str, 8);
	return a;
}
可以改成这样,把变换顺序的数据从新读回value,然后用memcpy来传送数据,

memcpy可以确保字节数为8个字节。

要注意的是,由于

value = (idata8 << 56) + (idata7 << 48) + (idata6 << 40) + (idata5 << 32) + (idata4 << 24) + (idata3 << 16) + (idata2 << 8) + idata1;
这一步要从新移位回去,所以idata1到idata8的类型要由__int8改为__int64,才能进行正确的移位。



你可能感兴趣的:(数据结构)