【发布时间】:2010-11-23 23:34:38
【问题描述】:
从文件中读取NSString 时,我可以使用initWithContentsOfFile:usedEncoding:error:,它会猜测文件的编码。
当我从NSData 创建它时,我唯一的选择是initWithData:encoding:,我必须在其中显式传递编码。当我使用NSData 而不是文件时,如何可靠地猜测编码?
【问题讨论】:
标签: cocoa-touch cocoa nsdata
从文件中读取NSString 时,我可以使用initWithContentsOfFile:usedEncoding:error:,它会猜测文件的编码。
当我从NSData 创建它时,我唯一的选择是initWithData:encoding:,我必须在其中显式传递编码。当我使用NSData 而不是文件时,如何可靠地猜测编码?
【问题讨论】:
标签: cocoa-touch cocoa nsdata
在 iOS 8 和 OS X 10.10 中,NSString 上有一个新 API:
Objective-C
+ (NSStringEncoding)stringEncodingForData:(NSData *)data
encodingOptions:(NSDictionary *)opts
convertedString:(NSString **)string
usedLossyConversion:(BOOL *)usedLossyConversion;
斯威夫特
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的值不是数组),则抛出异常。
如果字典中的值未知(例如,建议的字符串编码数组中的值不是有效编码),这些值将被忽略。
示例(斯威夫特):
var convertedString: NSString?
let encoding = NSString.stringEncoding(for: data, encodingOptions: nil, convertedString: &convertedString, usedLossyConversion: nil)
如果你只想要解码后的字符串而不关心编码,你可以删除let encoding =
【讨论】:
NSData 中查找字符串的编码。你的意图是什么?
一般来说,你不能。但是,您可以非常可靠地识别 UTF-8 文件——如果文件是有效的 UTF-8,那么它不太可能是任何其他编码(除非所有字节都在 ASCII 范围内,在这种情况下任何“扩展的 ASCII” 编码,包括 UTF-8,会给你同样的结果)。所有 Unicode 编码还有一个可选的BOM 来标识它们。所以一个合理的方法是:
initWithData:data encoding:NSUTF8StringEncoding 并检查结果是否为非零来做到这一点。-[NSString defaultCStringEncoding](提供适合区域设置的猜测)。可以尝试通过尝试各种不同的编码并选择中间包含垃圾的字母序列最少的编码来改进最后一步的猜测,其中“垃圾”是任何不是字母、空格或普通标点符号的字符。这会显着增加复杂性,但实际上并不可靠。
简而言之,为了能够处理所有可用的编码,您需要执行 TextEdit 所做的事情:将决定权交给用户。
哦,还有一件事:从 10.5 开始,编码通常与文件一起存储在未记录的 com.apple.TextEncoding 扩展属性中。如果您打开带有+[NSString stringWithContentsOfFile:] 或类似名称的文件,则会自动使用它(如果存在)。
【讨论】: