我在NSData上有以下类别方法。我尝试在给定索引处提取位字段并将其作为NSNumber返回。我让它完美地为所有积极工作,但我需要它与负数一起工作。
我的实施如下:
#import <Foundation/Foundation.h>
@interface NSData (ExternalDevices)
@end
@implementation NSData (ExternalDevices)
- (NSNumber *)extractLittleEndianBitFieldAtIndex:(int)index forLength:(int)length
{
//This function has limitations on the "length" parameter that are not yet know/defined
//These limitations are due to the max size of "NSInteger intData" defined below
int first_byte = index/8; //Index of the first byte containing this bit field
int last_byte = (length+index-1)/8; //Index of the last byte containing this bit field
int byte_length = last_byte - first_byte + 1; //number of bytes containing this bit field
Byte *byteArray = (Byte*)malloc(byte_length);
memcpy(byteArray, [[self subdataWithRange:NSMakeRange(first_byte, byte_length)] bytes], byte_length);
NSInteger intData = *((NSInteger *)byteArray);
free(byteArray);
return [NSNumber numberWithInt:intData];
}
+ (NSData *)dataFromHexString:(NSString *)string
{
string = [string lowercaseString];
NSMutableData *data= [NSMutableData new];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i = 0;
NSUInteger length = string.length;
while (i < length-1) {
char c = [string characterAtIndex:i++];
if (c < '0' || (c > '9' && c < 'a') || c > 'f')
continue;
byte_chars[0] = c;
byte_chars[1] = [string characterAtIndex:i++];
whole_byte = strtol(byte_chars, NULL, 16);
[data appendBytes:&whole_byte length:1];
}
return data;
}
@end
@interface Testing:NSObject
@end
@implementation Testing
- (instancetype)init
{
self = [super init];
if (self)
{
{
NSData *data = [NSData dataFromHexString:@"e30b"];
NSLog(@"%@ should be 3043", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]);
}
{
NSData *data = [NSData dataFromHexString:@"46e0"];
NSLog(@"%@ should be -8122", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]);
}
{
NSData *data = [NSData dataFromHexString:@"f208"];
NSLog(@"%@ should be 2290", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]);
}
{
NSData *data = [NSData dataFromHexString:@"10e6"];
NSLog(@"%@ should be -6640", [data extractLittleEndianBitFieldAtIndex:0 forLength:16]);
}
{
NSData *data = [NSData dataFromHexString:@"018900"];
NSLog(@"%@ should be 137", [data extractLittleEndianBitFieldAtIndex:8 forLength:16]);
}
}
return self;
}
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
[[Testing alloc] init];
}
}
以下网站似乎总能在INT16下产生我想要的结果 - Little Endian(BA)
http://www.scadacore.com/field-applications/miscellaneous/online-hex-converter.html
虽然重要的是要注意并非我使用的每个号码都是INT16
答案 0 :(得分:1)
你的专栏:
NSInteger intData = *((NSInteger *)byteArray);
是您的关键问题,原因有两个:
byteArray
可能比NSInteger
更短(或更不可能,更长),您最终会阅读垃圾。例如。如果你的例子中byteArray
是2个字节,NSInteger
是4个字节 - 它将是64位 - 你将读取两个字节的垃圾。
如果要转换有符号值,则需要对值进行符号扩展 - 即将符号位复制到较高的未使用位。例如。如果要将带符号的16位字段转换为32位有符号值,则高16位需要复制16位值的最高有效位,因此0x7000 - &gt; 0x00007000和0x8000 - &gt; 0xFFFF8000。
您需要提出一种处理这些问题的算法。您可能会发现使用屏蔽(和'),或者“移动”来转换一个字节更容易。
HTH