【问题标题】:Determine if UTF-8 encoded NSData contains a null-terminated string确定 UTF-8 编码的 NSData 是否包含以 null 结尾的字符串
【发布时间】:2023-03-17 07:55:02
【问题描述】:

我在 NSData 类别中有 NSData 到 NSString 的转换,因为我一直使用 NSString 方法:initWithData:encoding:。但是,根据https://stackoverflow.com/a/2467856/1231948这个答案,没那么简单。

到目前为止,我的 NSData 类别中有这个方法,以努力与其他数据对象中的方法保持一致,这些数据对象从同名方法返回字符串:

- (NSString *) stringValue
{
    return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
}

到目前为止它是成功的,但我想确定一个字符串是否以空结尾,来决定我是否应该改用这个方法,也来自答案链接:

NSString* str = [NSString stringWithUTF8String:[data bytes]];

如何确定 UTF-8 编码的 NSData 是否包含以 null 结尾的字符串?


得到下面的答案后,我为我的NSData分类方法写了更彻底的实现,stringValue

- (NSString *) stringValue
{
    //Determine if string is null-terminated
    char lastByte;
    [self getBytes:&lastByte range:NSMakeRange([self length]-1, 1)];

    NSString *str;

    if (lastByte == 0x0) {
        //string is null-terminated
        str = [NSString stringWithUTF8String:[self bytes]];
    } else {
        //string is not null-terminated
        str = [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
    }

    return str;
}

【问题讨论】:

  • 您从哪里获取数据?如果数据以空值结尾,它不应该是可变的或神秘的。例如,您显然可以确定它被编码为 UTF-8。无论协议规定什么,也应该规定它是否为空终止。 (例如,如果您不能保证它是否以 null 结尾,那么您如何确定它不是多个以 null 结尾的字符串的序列?或者由 null 分隔的多个字符串,这略有不同?)
  • 我不是要给出保证,而是一般性——我正在尝试构建一个足够强大的解决方案,以在各种情况下处理数据。你说得对,我限制为 UTF-8 有两个原因--1) UTF-8 是在线使用最广泛的字符编码(超过 80%),并且被 W3C 推荐为诸如以下语言的标准编码HTML 和 XML,2) 由于 UTF-8 是大多数情况下的标准,我希望将其他编码的处理保留在一个单独的方法中,该方法将编码作为第二个参数,这就是 Java 的 API 稍后设计的方式版本。
  • 根据我的经验,来自已知来源的数据不能保证为空终止。传输过程中会发生事情,最后的 0 可能会或可能不会到达。好问题。

标签: ios objective-c character-encoding nsstring nsdata


【解决方案1】:

空终止字面意思是最后一个字节的值为零。很容易检查:

char lastByte;
[myNSData getBytes:&lastByte range:NSMakeRange([myNSData length]-1, 1)];
if (lastByte == 0x0) {
    // string is null terminated
} else {
    // string is not null terminated
}

【讨论】:

  • 这正是您在将 NSData 转换为 NSString 遇到问题时所需要的。请参阅 kennytm 的回答:stackoverflow.com/questions/2467844/…。总结一下:如果 NSData 是空终止的,则使用 [NSString stringWithUTF8String:[theData bytes]],否则使用 [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding]。
【解决方案2】:

因此,您希望确定NSData 的最后一个字节是否为空,您知道如何获取指向所有字节的指针 (bytes) 以及有多少字节 (length)。

在 C 中,“指向所有字节的指针”可以用作数组并被索引,因此您可以使用以下方法获取最后一个字节:

Byte *theBytes = data.bytes;
Byte lastByte = theBytes[bytes.length - 1];

如果您需要支持以空字符结尾的字符串比整个缓冲区更短,您必须扫描它,记住在末尾停止(所以不要使用类似 strlen 的东西)。

在检查 null 时,您将同时获得指向字节和长度的指针,因为您可能希望使用 initWithBytes:length:encoding: 来构造 NSString 而不是问题中的两种方法中的任何一种。

HTH

【讨论】:

    猜你喜欢
    • 2013-02-17
    • 2012-12-23
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    相关资源
    最近更新 更多