将包含 UTF-8 和空字节的 NSData 转换为字符串
Converting NSData that contains UTF-8 and null bytes to string
我有一个 __NSCFData 对象。我知道里面是什么。
61 70 70 6c 65 2c 74 79 70 68 6f 6f 6e 00 41 52 4d 2c 76 38 00
我尝试使用 initWithData: 和 stringWithUTF8String: 将其转换为字符串,它给了我 "apple,typhoon"。转换终止于 00
实际数据是
61 a
70 p
70 p
6c l
65 e
2c ,
74 t
79 y
70 p
68 h
6f o
6f o
6e n
00 (null)
41 A
52 R
4d M
2c ,
76 v
38 8
00 (null)
如何在不丢失信息的情况下正确转换它?
0 或 null 是终止字符串的标记值,因此如果您想自动将字节转储到字符串中,您将不得不以某种方式处理它。如果不这样做,字符串或尝试打印它的东西,例如,将假定在到达 NULL 时已到达字符串末尾。
只需将出现的字节替换为可打印的内容,例如 space。使用适合您的值。
示例:
// original data you have from somewhere
char something[] = "apple,typhoon[=10=]ARM,v8[=10=]";
NSData *data = [NSData dataWithBytes:something length:sizeof(something)];
// Find each null terminated string in the data
NSMutableArray *strings = [NSMutableArray new];
NSMutableString *temp = [NSMutableString string];
const char *bytes = [data bytes];
for (int i = 0; i < [data length]; i++) {
unsigned char byte = (unsigned char)bytes[i];
if (byte == 0) {
if ([temp length] > 0) {
[strings addObject:temp];
temp = [NSMutableString string];
}
} else {
[temp appendFormat:@"%c", byte];
}
}
// Results
NSLog(@"strings count: %lu", [strings count]);
[strings enumerateObjectsUsingBlock:^(NSString *string, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%ld: %@", idx, string);
}];
// strings count: 2
// 0: apple,typhoon
// 1: ARM,v8
stringWithUTF8String
的文档将其第一个参数描述为:
A NULL-terminated C array of bytes in UTF8 encoding.
这就是为什么您的转换在第一个空字节处停止的原因。
您似乎拥有的是一组打包成单个 NSData
的 C 字符串。您可以单独转换每一个。使用NSData
方法bytes
和length
分别获取指向bytes/firstC字符串的指针和总字节数。标准 C 函数 strlen()
将为您提供单个字符串的字节长度。结合这些和一些简单的指针算法,您可以编写一个循环来转换每个字符串,例如,将它们全部存储到一个数组中或连接它们。
如果您在实施解决方案时遇到困难,请提出一个新问题,展示您的代码并解释问题。下一步肯定会有人帮助你。
HTH
与某些答案的意图相反,NSString
实例中存储的字符串 不是 0 终止的。即使写出它们可能存在问题(因为用于输出的底层 C 函数需要一个以 0 结尾的字符串),实例本身也可以包含 [=13=]
:
NSString *zeroIncluded = @"A[=10=]B";
NSLog(@"%ld", [zeroIncluded length]);
// prints 3
要创建这样的实例,您可以使用具有 bytes
和 length
参数的方法,即。 e. -initWithBytes:length:encoding:
。因此,这样的事情应该有效:
NSData *data = …
[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
但是,按照 CRD 的意图,您可能会检查是否需要这样的字符串。
我有一个 __NSCFData 对象。我知道里面是什么。
61 70 70 6c 65 2c 74 79 70 68 6f 6f 6e 00 41 52 4d 2c 76 38 00
我尝试使用 initWithData: 和 stringWithUTF8String: 将其转换为字符串,它给了我 "apple,typhoon"。转换终止于 00
实际数据是
61 a
70 p
70 p
6c l
65 e
2c ,
74 t
79 y
70 p
68 h
6f o
6f o
6e n
00 (null)
41 A
52 R
4d M
2c ,
76 v
38 8
00 (null)
如何在不丢失信息的情况下正确转换它?
0 或 null 是终止字符串的标记值,因此如果您想自动将字节转储到字符串中,您将不得不以某种方式处理它。如果不这样做,字符串或尝试打印它的东西,例如,将假定在到达 NULL 时已到达字符串末尾。
只需将出现的字节替换为可打印的内容,例如 space。使用适合您的值。
示例:
// original data you have from somewhere
char something[] = "apple,typhoon[=10=]ARM,v8[=10=]";
NSData *data = [NSData dataWithBytes:something length:sizeof(something)];
// Find each null terminated string in the data
NSMutableArray *strings = [NSMutableArray new];
NSMutableString *temp = [NSMutableString string];
const char *bytes = [data bytes];
for (int i = 0; i < [data length]; i++) {
unsigned char byte = (unsigned char)bytes[i];
if (byte == 0) {
if ([temp length] > 0) {
[strings addObject:temp];
temp = [NSMutableString string];
}
} else {
[temp appendFormat:@"%c", byte];
}
}
// Results
NSLog(@"strings count: %lu", [strings count]);
[strings enumerateObjectsUsingBlock:^(NSString *string, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%ld: %@", idx, string);
}];
// strings count: 2
// 0: apple,typhoon
// 1: ARM,v8
stringWithUTF8String
的文档将其第一个参数描述为:
A NULL-terminated C array of bytes in UTF8 encoding.
这就是为什么您的转换在第一个空字节处停止的原因。
您似乎拥有的是一组打包成单个 NSData
的 C 字符串。您可以单独转换每一个。使用NSData
方法bytes
和length
分别获取指向bytes/firstC字符串的指针和总字节数。标准 C 函数 strlen()
将为您提供单个字符串的字节长度。结合这些和一些简单的指针算法,您可以编写一个循环来转换每个字符串,例如,将它们全部存储到一个数组中或连接它们。
如果您在实施解决方案时遇到困难,请提出一个新问题,展示您的代码并解释问题。下一步肯定会有人帮助你。
HTH
与某些答案的意图相反,NSString
实例中存储的字符串 不是 0 终止的。即使写出它们可能存在问题(因为用于输出的底层 C 函数需要一个以 0 结尾的字符串),实例本身也可以包含 [=13=]
:
NSString *zeroIncluded = @"A[=10=]B";
NSLog(@"%ld", [zeroIncluded length]);
// prints 3
要创建这样的实例,您可以使用具有 bytes
和 length
参数的方法,即。 e. -initWithBytes:length:encoding:
。因此,这样的事情应该有效:
NSData *data = …
[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
但是,按照 CRD 的意图,您可能会检查是否需要这样的字符串。