0

我是Obj-Ccocoa的新程序员。我正在尝试编写一个用于读取二进制文件的框架(灵活的图像传输系统FITS二进制文件,通常由天文学家使用)。我有兴趣提取的二进制数据可以有多种格式,我通过读取FITS文件的标题来获取其属性。

到目前为止,我设法创建了一个类来存储FITS文件的内容,并将标头隔离到一个NSString对象中,并将二进制数据隔离到一个NSData对象中。我还设法编写了一种方法,该方法允许我从标题中提取对解释二进制数据非常有价值的键值。

我现在正在尝试将NSData对象转换为原始数组(数组doubleint... 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 int不是二元补码。我真的不熟悉这两个约定(IEEEtwos-complement),并且想知道如何使用Obj-C进行这种转换。

提前非常感谢您提供的任何帮助或信息。

4

4 回答 4

3

Objective-C 使用 IEEE-754 浮点数(就像几乎每个系统一样)以及二进制补码整数。我认为你的猜想是错误的。也许你有字节顺序问题?

于 2010-06-11T21:09:58.613 回答
1

几乎所有系统都使用二进制补码和 IEEE 754,仅仅是因为几乎不值得为这些事物提出全新的表示形式——除非您有非常特殊的情况需要它,否则您不会这样做。

我建议您以十六进制显示数字 - 与特殊格式的数据类型相比,它更可能是字节顺序问题,并且以十六进制打印值更容易判断这是否是问题。

于 2010-06-11T21:11:20.750 回答
0

你确定吗

double (*array)[NElements];

是你想要的吗?这个简单的程序:

int main( int argc, char** argv)
{
    double (*array)[5];
    (*array)[4] = 0;
    return 0;
}

在我的机器上惨遭崩溃。

于 2010-06-12T17:31:17.080 回答
0

非常感谢。这个问题真的与字节序有关,我没有意识到这一点。老实说,我从来没有真正意识到字节序类型,因为到目前为止,我从未遇到过这个问题。

顺便说一句,我找到了解决方案,谢谢大家的评论。因为它可能对其他开发人员有用,所以我将提出一种允许将 NSData 转换为原始类型的代码和平,无论是什么字节序类型。这是我找到的解决方案(在 Os X 10.5 和 10.6 上使用 Foundation 和 cocoa 框架),它可能不是最好的,因此,使用风险自负;)

// 1- CREATE AN ARRAY OF SIZE Nelements;
int Nelements = XXX;
double (*array)[Nelements];

// 2- Create the swapped double -> a double with the wrong bit order
NSSwappedDouble swappedValue;

// 3- The correct value
double Value;

// 4- Fill your array
int i=0, bit=0;
int BitStep=sizeof(double);

while(i<Nelements)
{
    [MyNSData getBytes:&swappedValue range:NSMakeRange(bit,step)];
    Value = NSSwapBigDoubleToHost(swappedValue);   // or NSSwapLittleDoubleToHost depending of your endian type.
    (*array)[i]=Value;
    i++; bit+=BitStep;

}

希望这会很有用。

于 2010-06-12T21:01:23.347 回答