代码之家  ›  专栏  ›  技术社区  ›  Cœur Gustavo Armenta

能否将stringEncodingForData:encodingOptions:convertedString:usedLossyConversion:return NSUTF16StringEncoding或NSUTF32StringEncoding?

  •  3
  • Cœur Gustavo Armenta  · 技术社区  · 6 年前

    我想知道你是否打电话来 stringEncodingForData:encodingOptions:convertedString:usedLossyConversion: 可以返回 NSUTF16StringEncoding , NSUTF32StringEncoding 或者他们的变种?

    documentation note on cStringUsingEncoding:

    特别注意事项

    this method 通过考试的结果 NSUTF16StringEncoding , NSUTF32StringEncoding

    字符串编码检测 stringEncodingForData:编码选项:convertedString:usedLossyConversion: 可以返回UTF-16和UTF-32,也可以不返回。

    示例场景(改编自 SSZipArchive.m

    // name is a null-terminated C string built with `fread` from stdio.h:
    char *name = (char *)malloc(size_name + 1);
    size_t read = fread(name, 1, size_name + 1, file);
    name[size_name] = '\0';
    
    // dataName is the data object of name
    NSData *dataName = [NSData dataWithBytes:(const void *)name length:sizeof(unsigned char) * size_name];
    
    // stringName is the string object of dataName
    NSString *stringName = nil;
    NSStringEncoding encoding = [NSString stringEncodingForData:dataName encodingOptions:nil convertedString:&stringName usedLossyConversion:nil];
    

    在上述代码中,可以 encoding , 或者他们的变种?


    平台:macOS 10.10+、iOS 8.0+、watchOS 2.0+、tvOS 9.0+。

    1 回复  |  直到 6 年前
        1
  •  4
  •   Rob Napier    6 年前

    是的,如果字符串是使用这些编码之一编码的。关于C字符串的注释是特定于C字符串的。NSString不是C字符串,您描述的方法对C字符串不起作用;它可以处理任意数据,这些数据可以用多种方式编码。

    例如:

    #import <Foundation/Foundation.h>
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            NSData *data = [@"test" dataUsingEncoding:NSUTF16StringEncoding];
            NSStringEncoding encoding = [NSString stringEncodingForData:data
                                                        encodingOptions:nil
                                                        convertedString:nil
                                                    usedLossyConversion:nil];
            NSLog(@"%ld == %ld", (unsigned long)encoding, 
                                 (unsigned long)NSUTF16StringEncoding);
        }
        return 0;
    }
    // Output:   10 == 10
    

    也就是说,在你的例子中,如果 name 实际上就是它所说的“一个以null结尾的C字符串”,那么它就永远不可能是UTF-16,因为C字符串不能用UTF-16编码。C字符串是以\0结尾的,而\0是UTF-16中一个非常常见的字符。但是,如果没有看到更多的代码,我就不会赌这个注释是否准确。

    如果你真正的问题是“给定一个任意的c字符串安全编码,有没有可能 stringEncodingForData: 将返回一个非c-string-safe编码”,然后答案是“是的,它可以,而且它肯定不会承诺它不会,即使它今天没有。”如果你需要防止,我建议使用 NSStringEncodingDetectionSuggestedEncodingsKey ...UseOnlySuggestedEncodingsKey 强迫它成为你能处理的编码(你也可以用 ...DisallowedEncodingsKey