在 Objective-C / C 中读取 9 位、10 位或 11 位(精确)块中的数据并转换为整数

发布于 2025-01-08 05:31:01 字数 297 浏览 0 评论 0原文

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

101001110 001011100 001101010 101010110 100001011 等。

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

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

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

I'm reading measurement data that is saved in 9 bit binary form with no spacing, e.g.

101001110 001011100 001101010 101010110 100001011 etc.

The data is from old measurement equipment, and sometimes, I have to read in chunks of e.g. 10, 11, or 12 bits. I will always know what integer size to read as there's some file info in the beginning of the file.

But in iOS / Objective-C I know only how to get binary data down to the size of 8 bit bytes, e.g. Int8, int16 etc. And convert those 8- or 16-bit chunks to integers.

How do I step through say an NSData object in bit-wise predefined steps?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心的位置 2025-01-15 05:31:01

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

@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 艾字节,您可以显式使用 64 位长。

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

You'd have to write your own deserialiser. For example:

@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

And:

@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

All untested, but hopefully correct. Notice that I'm counting bits in an NSUInteger, which from memory are 32 bits wide under iOS so the maximum file size it can cope with is 512mb. You could explicitly use a 64 bit long long if you wanted to go to 2 exabytes.

The obvious next thing to add would be a Boolean getter for whether the stream is finished.

我很OK 2025-01-15 05:31:01

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

If you know the file is either all 9, all 10, or all 11 bit values, the thing I'd probably do is write three separate algorithms to extract the data in those lengths, vs trying to write a "generic" routine. Mostly you can handle the logic for a given size by having a switch statement for the 8 possible alignments for each value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文