我有一个__NSCFData对象。我知道里面有什么。
61 70 70 6c 65 2c 74 79 70 68 6f 6f 6e 00 41 52 4d 2c 76 38 00
我尝试使用initWithData:和stringWithUTF8String将其转换为字符串:它给了我“苹果,台风”。转换终止于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 :(得分:3)
stringWithUTF8String
的文档将其第一个参数描述为:
以UTF8编码的以NULL结尾的C字节数组。
这就是您的转换在第一个空字节处停止的原因。
您似乎拥有的是包含在单个NSData
中的C字符串集合。您可以单独转换每一个。使用NSData
方法bytes
和length
分别获取指向字节/第一个C字符串和总字节数的指针。标准C函数strlen()
将为您提供单个字符串的字节长度。结合这些和一些简单的指针算法,您可以编写一个转换每个字符串的循环,例如,将它们全部存储到数组中或连接它们。
如果您遇到问题,请执行解决方案,提出新问题,展示代码并解释问题。毫无疑问,有人会帮助你完成下一步。
HTH
答案 1 :(得分:0)
0或null,是终止字符串的sentinel值,因此如果要将字节自动转储到字符串中,您将不得不以某种方式处理它。如果不这样做,例如,字符串或尝试打印它的东西将假定在达到NULL时达到字符串的结尾。
只需将字节替换为可打印的字节,如空格。使用适合你的任何价值。
示例:
// original data you have from somewhere
char something[] = "apple,typhoon\0ARM,v8\0";
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
答案 2 :(得分:0)
与某些答案的意图相反,NSString
实例中存储的字符串不 0终止。即使写出来也可能有问题(因为输出的底层C函数需要一个以0结尾的字符串),实例本身可以包含\0
:
NSString *zeroIncluded = @"A\0B";
NSLog(@"%ld", [zeroIncluded length]);
// prints 3
要创建此类实例,您可以使用具有bytes
和length
参数的方法,即。即-initWithBytes:length:encoding:
。因此,这样的事情应该有效:
NSData *data = …
[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
但是,正如CRD所预期的那样,您可以检查是否要使用这样的字符串。