使用 ieee-754 或二进制补码将 NSData 转换为原始变量?
我是 Obj-C 和 cocoa 的新程序员。我正在尝试编写一个用于读取二进制文件的框架(灵活图像传输系统或FITS二进制文件,通常由天文学家使用)。我有兴趣提取的二进制数据可以有多种格式,我通过读取 FITS 文件的标头来获取其属性。
到目前为止,我设法创建一个类来存储 FITS 文件的内容,并将标头隔离到 NSString
对象中,将二进制数据隔离到 NSData
对象。我还设法编写了一种方法,该方法允许我从标头中提取对于解释二进制数据非常有价值的键值。
我现在尝试将 NSData
对象转换为原始数组(double
, int
, short
数组。 ..)。但是,在这里,我陷入困境,希望得到任何帮助。
根据我关于 FITS 文件的文档,我有 5 种可能性来解释二进制数据,具体取决于 BITPIX 键的值:
BITPIX value | Data represented
8 | Char or unsigned binary int
16 | 16-bit two's complement binary integer
32 | 32-bit two's complement binary integer
64 | 64-bit two's complement binary integer
-32 | IEEE single precision floating-point
-64 | IEEE double precision floating-point
我已经编写了和平的代码,如下所示,尝试将 NSData
转换为原始数组。
// self reefer to my FITS class which contain a NSString object
// with the content of the header and a NSData object with the binary data.
-(void*) GetArray
{
switch (BITPIX)
{
case 8:
return [self GetArrayOfUInt];
break;
case 16:
return [self GetArrayOfInt];
break;
case 32:
return [self GetArrayOfLongInt];
break;
case 64:
return [self GetArrayOfLongLong];
break;
case -32:
return [self GetArrayOfFloat];
break;
case -64:
return [self GetArrayOfDouble];
break;
default:
return NULL;
}
}
// then I show you the method to convert the NSData into a primitive array.
// I restrict my example to the case of 'double'. Code is similar for other methods
// just change double by 'unsigned int' (BITPIX 8), 'short' (BITPIX 16)
// 'int' (BITPIX 32) 'long lon' (BITPIX 64), 'float' (BITPIX -32).
-(double*) GetArrayOfDouble
{
int Nelements=[self NPIXEL]; // Metod to extract, from the header
// the number of element into the array
NSLog(@"TOTAL NUMBER OF ELEMENTS [%i]\n",Nelements);
//CREATE THE ARRAY
double (*array)[Nelements];
// Get the total number of bits in the binary data
int Nbit = abs(BITPIX)*GCOUNT*(PCOUNT + Nelements); // GCOUNT and PCOUNT are defined
// into the header
NSLog(@"TOTAL NUMBER OF BIT [%i]\n",Nbit);
int i=0;
//FILL THE ARRAY
double Value;
for(int bit=0; bit < Nbit; bit+=sizeof(double))
{
[Img getBytes:&Value range:NSMakeRange(bit,sizeof(double))];
NSLog(@"[%i]:(%u)%.8G\n",i,bit,Value);
(*array)[i]=Value;
i++;
}
return (*array);
}
然而,我在循环中打印的值与预期值有很大不同(与使用官方 FITS 软件相比)。因此,我认为 Obj-C double
不使用 IEEE-754 约定以及 Obj-C< /strong> int
不是补码。我真的不熟悉这两个约定(IEEE 和 twos-complement),并且想知道如何使用 Obj-C 进行此转换强>。
预先非常感谢您的任何帮助或信息。
I am new programmer in Obj-C and cocoa. Im a trying to write a framework which will be used to read a binary files (Flexible Image Transport System or FITS binary files, usually used by astronomers). The binary data, that I am interested to extract, can have various formats and I get its properties by reading the header of the FITS file.
Up to now, I manage to create a class to store the content of the FITS file and to isolate the header into a NSString
object and the binary data into a NSData
object. I also manage to write method which allow me to extract the key values from the header that are very valuable to interpret the binary data.
I am now trying to convert the NSData
object into a primitive array (array of double
, int
, short
...). But, here, I get stuck and would appreciate any help.
According to the documentation I have about the FITS file, I have 5 possibilities to interpret the binary data depending on the value of the BITPIX
key:
BITPIX value | Data represented
8 | Char or unsigned binary int
16 | 16-bit two's complement binary integer
32 | 32-bit two's complement binary integer
64 | 64-bit two's complement binary integer
-32 | IEEE single precision floating-point
-64 | IEEE double precision floating-point
I already write the peace of code, shown bellow, to try to convert the NSData
into a primitive array.
// self reefer to my FITS class which contain a NSString object
// with the content of the header and a NSData object with the binary data.
-(void*) GetArray
{
switch (BITPIX)
{
case 8:
return [self GetArrayOfUInt];
break;
case 16:
return [self GetArrayOfInt];
break;
case 32:
return [self GetArrayOfLongInt];
break;
case 64:
return [self GetArrayOfLongLong];
break;
case -32:
return [self GetArrayOfFloat];
break;
case -64:
return [self GetArrayOfDouble];
break;
default:
return NULL;
}
}
// then I show you the method to convert the NSData into a primitive array.
// I restrict my example to the case of 'double'. Code is similar for other methods
// just change double by 'unsigned int' (BITPIX 8), 'short' (BITPIX 16)
// 'int' (BITPIX 32) 'long lon' (BITPIX 64), 'float' (BITPIX -32).
-(double*) GetArrayOfDouble
{
int Nelements=[self NPIXEL]; // Metod to extract, from the header
// the number of element into the array
NSLog(@"TOTAL NUMBER OF ELEMENTS [%i]\n",Nelements);
//CREATE THE ARRAY
double (*array)[Nelements];
// Get the total number of bits in the binary data
int Nbit = abs(BITPIX)*GCOUNT*(PCOUNT + Nelements); // GCOUNT and PCOUNT are defined
// into the header
NSLog(@"TOTAL NUMBER OF BIT [%i]\n",Nbit);
int i=0;
//FILL THE ARRAY
double Value;
for(int bit=0; bit < Nbit; bit+=sizeof(double))
{
[Img getBytes:&Value range:NSMakeRange(bit,sizeof(double))];
NSLog(@"[%i]:(%u)%.8G\n",i,bit,Value);
(*array)[i]=Value;
i++;
}
return (*array);
}
However, the value I print in the loop are very different from the expected values (compared using official FITS software). Therefore, I think that the Obj-C double
does not use the IEEE-754 convention as well as the Obj-C int
are not twos-complement. I am really not familiar with this two convention (IEEE and twos-complement) and would like to know how I can do this conversion with Obj-C.
In advance many thanks for any help or information.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Objective-C 使用 IEEE-754 浮点数(就像几乎每个系统一样)以及二进制补码整数。我认为你的推测是错误的。也许您遇到字节序问题?
Objective-C uses IEEE-754 floats (like practically every system does) as well as two's-complement integers. I think your conjecture is false. Maybe you are having endianness problems?
几乎所有系统都使用二进制补码和 IEEE 754,仅仅是因为很少值得为这些事物提出全新的表示形式 - 除非您有非常特殊的情况需要它,否则您不会这样做。
我建议您以十六进制显示数字 - 与特殊格式的数据类型相比,这更有可能是字节序问题,并且以十六进制打印值可以更容易地判断这是否是问题。
Virtually all systems use two's complement and IEEE 754, simply because it is rarely worth it to come up with a brand new representation of these things - you just don't do that unless you have very specialized circumstances that require it.
I would suggest you display the number in hexadecimal - it is much more likely to be an issue with endianness than the data types being of a special format, and printing the values in hexadecimal makes it easier to tell if that is the problem.
您确定这
就是您想要的吗?这个简单的程序:
在我的机器上严重崩溃。
Are you sure that
is what you want? This simple program:
Crashes miserably on my machine.
多谢。这个问题确实与字节序有关,但我没有意识到这一点。老实说,我从来没有真正意识到字节序类型,因为到目前为止,我从未遇到过这个问题。
顺便说一句,我找到了解决方案,谢谢大家的评论。因为它对其他开发人员很有用,所以我将提出一种和平的代码,允许将 NSData 转换为原始类型,无论是什么字节序类型。这是我找到的解决方案(在 Os X 10.5 和 10.6 上使用 Foundation 和 cocoa 框架),它可能不是最好的,因此,使用风险自负;)
希望这会很有用。
Thanks a lot. The problem was really related to the endian and I was not aware of this. Honestly, I was never really aware of the endian type because, up to now, I was never confronted to the problem.
By the way, I find the solution, thanks all for your remarks. Because it can be useful for other developer, I will propose a peace of code which allow to convert NSData to primitive, what ever the endian type. This is the solution I find (work with the Foundation and cocoa framework on Os X 10.5 and 10.6) and it may not be the best, so, use at your own risk ;)
Hope this can be useful.