从文件读取NSString
时,可以使用initWithContentsOfFile:usedEncoding:error:
方法来猜测文件的编码。
但是,如果我是从NSData
创建字符串,那么我只能使用initWithData:encoding:
方法,需要显式指定编码。在使用NSData
而不是文件时,如何可靠地猜测编码?
从文件读取NSString
时,可以使用initWithContentsOfFile:usedEncoding:error:
方法来猜测文件的编码。
但是,如果我是从NSData
创建字符串,那么我只能使用initWithData:encoding:
方法,需要显式指定编码。在使用NSData
而不是文件时,如何可靠地猜测编码?
NSString
上有一个新的API:
Objective-C
+ (NSStringEncoding)stringEncodingForData:(NSData *)data
encodingOptions:(NSDictionary *)opts
convertedString:(NSString **)string
usedLossyConversion:(BOOL *)usedLossyConversion;
Swift
open class func stringEncoding(for data: Data,
encodingOptions opts: [StringEncodingDetectionOptionsKey : Any]? = nil,
convertedString string: AutoreleasingUnsafeMutablePointer<NSString?>?,
usedLossyConversion: UnsafeMutablePointer<ObjCBool>?) -> UInt
现在你可以让这个框架猜测,根据我的经验那通常是很有效的!
从标题中可以看出(文档目前没有说明方法,但它在WWDC Session 204 (page 270)中被正式提到):
- 推荐的字符串编码数组(如果不指定列表中的第3个选项,则将考虑所有字符串编码,但数组中的编码会优先考虑;此外,数组中编码的顺序很重要:第一个编码比数组中的第二个编码更受欢迎)
- 不使用的字符串编码数组(该列表中的字符串编码将根本不予考虑)
- 一个布尔选项,指示是否仅考虑建议的字符串编码
- 一个布尔选项,指示是否允许损失
- 给定要替换为神秘字节的特定字符串的选项
- 当前用户的语言
- 一个布尔选项,指示数据是否由Windows生成
如果字典中的值类型错误(例如,NSStringEncodingDetectionSuggestedEncodingsKey的值不是数组),则会抛出异常。
如果字典中的值未知(例如,建议的字符串编码数组中的值不是有效编码),则这些值将被忽略。
示例(Swift):
var convertedString: NSString?
let encoding = NSString.stringEncoding(for: data, encodingOptions: nil, convertedString: &convertedString, usedLossyConversion: nil)
如果您只需要解码后的字符串并不关心编码,可以删除let encoding =
initWithData:data encoding:NSUTF8StringEncoding
并检查结果是否为非nil来实现此目的。-[NSString defaultCStringEncoding]
(提供一个与本地环境相符的猜测)。在最后一步中,可以尝试通过尝试各种不同的编码方式,并选择其中具有最少字符序列junk(即任何不是字母、空格或常见标点符号的字符)的一个来改善猜测。这将显著增加复杂度,而实际上并不可靠。
简而言之,要能够处理所有可用的编码方式,你需要像TextEdit那样:把决定权交给用户。
哦,还有一件事:从10.5开始,编码方式通常与文件一起存储在未记录的com.apple.TextEncoding扩展属性中。如果你使用+[NSString stringWithContentsOfFile:]
或类似方法打开一个文件,则如果存在该属性,则会自动使用它。
NSData
中查找字符串的编码方式。你的意图是什么? - HAS