Objective-C中有任何方法可以将十六进制字符串转换为字节吗?例如@"1156FFCD3430AA22"
至unsigned char array {0x11, 0x56, 0xFF, ...}
。NSString(十六进制)到字节
回答
不像你这样做。您需要编写自己的方法来获取每两个字符,将它们解释为一个int,然后将它们存储在一个数组中。
的scanHexInt:
和NSScanner
类似的方法可能是在做你想要什么有益的,但你可能会需要向上突破字符串成小块第一,在这种情况下做翻译手动可能会比使用NSScanner
简单。
@interface NSString (NSStringHexToBytes)
-(NSData*) hexToBytes ;
@end
@implementation NSString (NSStringHexToBytes)
-(NSData*) hexToBytes {
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= self.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [self substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
return data;
}
@end
/// example
unsigned char bytes[] = { 0x11, 0x56, 0xFF, 0xCD, 0x34, 0x30, 0xAA, 0x22 };
NSData* expectedData = [NSData dataWithBytes:bytes length:sizeof(bytes)];
NSLog(@"data %@", [@"1156FFCD3430AA22" hexToBytes]);
NSLog(@"expectedData isEqual:%d", [expectedData isEqual:[@"1156FFCD3430AA22" hexToBytes]]);
修订的方法,
/* Converts a hex string to bytes.
Precondition:
. The hex string can be separated by space or not.
. the string length without space or 0x, must be even. 2 symbols for one byte/char
. sample input: 23 3A F1 OR 233AF1, 0x23 0X231f 2B
*/
+ (NSData *) dataFromHexString:(NSString*)hexString
{
NSString * cleanString = [Util cleanNonHexCharsFromHexString:hexString];
if (cleanString == nil) {
return nil;
}
NSMutableData *result = [[NSMutableData alloc] init];
int i = 0;
for (i = 0; i+2 <= cleanString.length; i+=2) {
NSRange range = NSMakeRange(i, 2);
NSString* hexStr = [cleanString substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
unsigned char uc = (unsigned char) intValue;
[result appendBytes:&uc length:1];
}
NSData * data = [NSData dataWithData:result];
[result release];
return data;
}
/* Clean a hex string by removing spaces and 0x chars.
. The hex string can be separated by space or not.
. sample input: 23 3A F1; 233AF1; 0x23 0x3A 0xf1
*/
+ (NSString *) cleanNonHexCharsFromHexString:(NSString *)input
{
if (input == nil) {
return nil;
}
NSString * output = [input stringByReplacingOccurrencesOfString:@"0x" withString:@""
options:NSCaseInsensitiveSearch range:NSMakeRange(0, input.length)];
NSString * hexChars = @"abcdefABCDEF";
NSCharacterSet *hexc = [NSCharacterSet characterSetWithCharactersInString:hexChars];
NSCharacterSet *invalidHexc = [hexc invertedSet];
NSString * allHex = [[output componentsSeparatedByCharactersInSet:invalidHexc] componentsJoinedByString:@""];
return allHex;
}
最快的NSString类实现:
- (NSData *)dataFromHexString {
const char *chars = [self UTF8String];
int i = 0, len = self.length;
NSMutableData *data = [NSMutableData dataWithCapacity:len/2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
}
return data;
}
这是接近8倍的速度比wookay的解决方案。 NSScanner非常慢。在雨燕2.2
+1这似乎更好 - 不仅更快,但这实际上是正确的。** – 2013-07-07 11:35:44
非常好的实施。 – 2013-11-27 20:13:29
好的实现,但如果你需要错误检查,你需要在调用'strtoul'之前将'errno'设置为0,然后再读取它。 – Joe 2017-10-17 01:16:01
第一次尝试:
func hexStringToBytes(hexString: String) -> NSData? {
guard let chars = hexString.cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
var i = 0
let length = hexString.characters.count
let data = NSMutableData(capacity: length/2)
var byteChars: [CChar] = [0, 0, 0]
var wholeByte: CUnsignedLong = 0
while i < length {
byteChars[0] = chars[i]
i+=1
byteChars[1] = chars[i]
i+=1
wholeByte = strtoul(byteChars, nil, 16)
data?.appendBytes(&wholeByte, length: 1)
}
return data
}
或者,作为字符串的扩展:
extension String {
func dataFromHexString() -> NSData? {
guard let chars = cStringUsingEncoding(NSUTF8StringEncoding) else { return nil}
var i = 0
let length = characters.count
let data = NSMutableData(capacity: length/2)
var byteChars: [CChar] = [0, 0, 0]
var wholeByte: CUnsignedLong = 0
while i < length {
byteChars[0] = chars[i]
i+=1
byteChars[1] = chars[i]
i+=1
wholeByte = strtoul(byteChars, nil, 16)
data?.appendBytes(&wholeByte, length: 1)
}
return data
}
}
这是一个持续的工作正在进行中,但似乎很好地工作至今。
进一步优化和更深入的讨论可以在Code Review找到。
是不是这只是[这个答案](http://stackoverflow.com/a/17511588/865175)的Swift翻译? – 2016-11-23 17:36:33
几个溶液返回错误值,如果像这样 字符串 “DBA”
正确为 “DBA” 数据串是“\ X0D \ XBA”(int值:3514)
,如果你有一个数据是不喜欢这个“\ X0D \ XBA”它意味着你有一个错误的字节,因为该值会有所不同,例如,你得到的数据是这样“\ XDB \ X0A”该int值是56074
这里是重写的解决方案:
+ (NSData *)dataFromHexString:(NSString *) string {
if([string length] % 2 == 1){
string = [@"0"stringByAppendingString:string];
}
const char *chars = [string UTF8String];
int i = 0, len = (int)[string length];
NSMutableData *data = [NSMutableData dataWithCapacity:len/2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:1];
}
return data;
}
- 1. 十六进制字符串到NSString
- 2. C#字符串为十六进制,十六进制到字节转换
- 3. 将字符串转换为十六进制到十六进制
- 4. 十六进制字符串到十六进制整数
- 5. 将4字节十六进制转换为十进制值
- 6. VB.Net - 将多字节十六进制值转换为十进制
- 7. 将从1M字节为十六进制
- 8. 双字节十六进制值
- 9. 十六进制字节组串
- 10. NSString integerValue返回十六进制数
- 11. 将NSString转换为十六进制
- 12. NSString和UTF8十六进制转换
- 13. 将十进制转换为十六进制和十六进制
- 14. 转换十六进制字符串十六进制值
- 15. 十六进制字符串到Ruby中的字节数组
- 16. bigquery十六进制字符串到字节/ int
- 17. linux shell脚本:十六进制字符串到字节
- 18. 图像十六进制字符串到字节[]转换
- 19. 添加十六进制值以得到十六进制结果
- 20. 用于大数字的十进制到十六进制的Python
- 21. 十六进制
- 22. 十六进制
- 23. 十六进制字符?
- 24. 将字节数组转换为十六进制十进制字符串
- 25. 十六进制,八进制,二进制到十进制(C++)
- 26. 如何转换的NSString二进制和二进制到十六进制
- 27. Python - 如何编辑字节的十六进制文件字节
- 28. MIPS的int由字节读字节为十六进制
- 29. 将二进制读入十六进制字节数组
- 30. 长到十六进制字符串
纠正我,如果我错了,但我认为[数据对appendBytes:长的intValue:1]有一些麻烦。类型无符号整型至少有四个字符宽(至少保持32位)。 &intValue是指向四个中第一个的指针。这意味着,在小端系统中,&intValue将正确地成为您刚刚扫描的字符的指针。但在大端架构中,它始终指向一个零值,因为该值是作为四个字符中的最后一个存储的。基本上这意味着这段代码可以在Mac上运行并在iOS上破解。 – Trenskow 2012-08-22 23:45:59
这个答案有很多缺陷。它不仅将int视为一个字节(根据C标准,这是不可能的),而且它仅仅会产生大量的子字符串,而不是仅仅遍历可以使用的'const char * 'UTF8String' ... – 2013-07-07 11:34:29