String(contentsOf: URL).data(using: .utf8)与Data(contentsOf: URL)的差异疑问
两种Swift读取JSON文件方式的区别
这两种读取方式存在本质差异,并非只是默认编码的区别,核心差异在于处理流程和数据转换逻辑:
1. 执行流程差异
第一种方式:
do { let jsonData = try String(contentsOf: url).data(using: .utf8) } catch { ... }分为两步:
- 读取文件字节流,尝试自动识别文件编码,将其解析为
String(如果编码无法识别会抛出错误)。 - 将解析后的
String转换为UTF-8编码的Data,相当于完成了一次编码转译。
- 读取文件字节流,尝试自动识别文件编码,将其解析为
第二种方式:
do { let jsonData = try Data(contentsOf: url) } catch { ... }直接读取文件的原始二进制字节流,不做任何编码解析或转换,拿到的是文件里的原始数据。
2. 实际场景中的差异表现
场景1:文件为标准UTF-8编码(无BOM)
两种方式最终得到的Data内容看起来一致,但执行效率不同——第一种多了「字节→字符串→UTF-8字节」的转码开销,第二种更高效。
场景2:文件为UTF-16/UTF-32编码(JSON规范允许的编码)
- 第一种方式:会先将UTF-16/UTF-32的字节解析为
String,再转成UTF-8编码的Data,最终得到的是UTF-8格式的字节,和原始文件字节完全不同。 - 第二种方式:保留原始的UTF-16/UTF-32字节流,JSON解析器(如
JSONDecoder、JSONSerialization)可以自动识别这些编码(通过字节顺序标记BOM或字节特征),正常解析JSON。
场景3:文件为非JSON规范编码(如GBK)
- 第一种方式:如果
String(contentsOf:)无法识别GBK编码,会直接抛出错误;即使识别成功,转成UTF-8后的Data也不符合JSON规范,解析会失败。 - 第二种方式:拿到原始GBK字节流,JSON解析器无法识别该编码,解析同样失败,但不会提前抛出错误。
3. 选型建议
- 如果你明确JSON文件是UTF-8编码,两种方式都能用,但优先选第二种(更高效)。
- 如果需要兼容JSON规范允许的所有编码(UTF-8/UTF-16/UTF-32),必须选第二种——第一种会强制转成UTF-8,虽然不影响解析,但额外的转码是不必要的开销。
- 如果你需要确保数据是UTF-8编码,第一种方式可以实现编码转换,但前提是文件编码能被
String(contentsOf:)正确识别。
内容的提问来源于stack exchange,提问作者SouthernYankee65
相关产品推荐
相关产品推荐

