【问题标题】:Read data in 9-, 10-, or 11-bit (exact) chunks and convert to integer in Objective-C / C读取 9、10 或 11 位(精确)块中的数据并在 Objective-C / C 中转换为整数
【发布时间】:2012-03-14 11:07:28
【问题描述】:

我正在读取以 9 位二进制格式保存的测量数据,没有空格,例如

101001110 001011100 001101010 101010110 100001011 等

数据来自旧的测量设备,有时,我必须读取大块的数据,例如10、11 或 12 位。我总是知道要读取的整数大小,因为文件开头有一些文件信息。

但在 iOS/Objective-C 中,我只知道如何将二进制数据缩小到 8 位字节的大小,例如Int8、int16 等。并将这些 8 位或 16 位块转换为整数。

如何以按位预定义的步骤逐步执行 NSData 对象?

【问题讨论】:

  • bithacks page 上的大多数例程都是为正常大小的数字设计的,但我预测在不久的将来你会比普通程序员编写更多的比特旋转代码,而这指南可能会在晚上温暖你的心。
  • 除了位移和仔细跟踪您所在的位置之外,没有“简单”的方法可以做到这一点
  • 这甚至不值得成为一个问题,更不用说有答案了。我的意思是,在 C 语言中,您只能将文件读取为整个字符的倍数(通常为 8 位长),对此您无能为力。
  • @Alex 如果可以的话,我会对该评论进行-1。只需看看其他回复,看看它有多么错误。

标签: objective-c c binary integer nsdata


【解决方案1】:

您必须编写自己的反序列化器。例如:

@interface CHBinaryStream

// init with an NSData from which values will be read
- (id)initWithData:(NSData *)data;

// e.g. readBits:9 will assemble 9 bits from the data stream,
// return them in the low 9 bits of an NSUInteger. If you
// ask for more bits than an NSUInteger can store then they'll
// just drop off the end. This will also advance the read pointer
// by 9 bits
- (NSUInteger)readBits:(int)numberOfBits;

@end

还有:

@implementation CHBinaryStream
{
     NSData *sourceData;
     NSUInteger readPointer;
}

- (id)initWithData:(NSData *)data
{
    self = [super init];

    if(self)
    {
        sourceData = [data retain];
    }

    return self;
}

- (void)dealloc
{
    [sourceData release], sourceData = nil;
    [super dealloc];
}

- (NSUInteger)readBit
{
    // we'll just return a stream of 0s if we
    // go past the end of the source data
    if((readPointer >> 3) >= [sourceData length]) return 0;

    // otherwise we'll read the byte at:
    //
    //    sourceData >> 3
    //
    // and return the bit at:
    //
    //    sourceData & 7
    //
    // (where for our purposes, the 0th bit in a byte
    // is the most significant)
    uint8_t sourceByte = ((uint8_t *)[sourceData bytes])[sourceData >> 3];

    sourceByte <<= sourceData&7; // the bit we want is now where the MSB was
    sourceByte >>= 7;            // the bit we want is now in the LSB
    sourceByte &= 1;             // this clears all the other bits

    /*

         Alternative: (sourceByte >> ((sourceData & 7) ^ 7))&1;

    */

    // advance the read pointer, and then return the value
    readPointer++;

    return sourceByte;
}


- (NSUInteger)readBits:(int)numberOfBits
{
     NSUInteger result = 0;

     // shift in the required number of bits;
     // since we're going to get the most significant
     // bits first, we add incoming bits in the least
     // significant location and shift upward

     while(numberOfBits--)
         result = (result << 1) | [self readBit];

     return result;
}

@end

所有未经测试,但希望是正确的。请注意,我正在计算 NSUInteger 中的位数,它在 iOS 下内存为 32 位宽,因此它可以处理的最大文件大小为 512mb。如果您想达到 2 EB,可以显式使用 64 位长。

接下来要添加的显然是一个布尔 getter,用于指示流是否完成。

【讨论】:

  • 谢谢。我会试试你的 sn-p 代码。我的文件不是那么大,只有几兆字节,其中填充了整数,长度因文件而异(但在文件中相同)。
【解决方案2】:

如果您知道文件是全部 9、全部 10 或全部 11 位值,我可能会编写三个单独的算法来提取这些长度的数据,而不是尝试编写“通用”常规。大多数情况下,您可以通过为每个值的 8 种可能对齐方式设置一个 switch 语句来处理给定大小的逻辑。

【讨论】:

    猜你喜欢
    • 2011-06-01
    • 2010-12-07
    • 2013-08-02
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    • 2016-09-06
    相关资源
    最近更新 更多