我正在读取以无间距的 9 位二进制形式保存的测量数据,例如
101001110 001011100 001101010 101010110 100001011 等
数据来自旧的测量设备,有时,我必须大块地阅读,例如10、11 或 12 位。我将始终知道要读取的整数大小,因为文件开头有一些文件信息。
但是在 iOS/Objective-C 中,我只知道如何将二进制数据缩小到 8 位字节的大小,例如Int8、int16 等。并将这些 8 位或 16 位 block 转换为整数。
我如何以按位预定义的步骤遍历 NSData 对象?
最佳答案
您必须编写自己的反序列化器。例如:
@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 位 long。
接下来要添加的显然是一个 bool 值 getter,用于判断流是否结束。
关于objective-c - 读取 9 位、10 位或 11 位(精确) block 中的数据并在 Objective-C/C 中转换为整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9423302/