将包含UTF-8和null字节的NSData转换为字符串

时间:2017-10-27 17:03:22

标签: objective-c string nsdata c-strings

我有一个__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)

如何在不丢失信息的情况下正确转换?

3 个答案:

答案 0 :(得分:3)

stringWithUTF8String的文档将其第一个参数描述为:

  

以UTF8编码的以NULL结尾的C字节数组。

这就是您的转换在第一个空字节处停止的原因。

您似乎拥有的是包含在单个NSData中的C字符串集合。您可以单独转换每一个。使用NSData方法byteslength分别获取指向字节/第一个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

要创建此类实例,您可以使用具有byteslength参数的方法,即。即-initWithBytes:length:encoding:。因此,这样的事情应该有效:

NSData *data = …
[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];

但是,正如CRD所预期的那样,您可以检查是否要使用这样的字符串。