Swift(iOS/macOS)中的CSV处理:从简单到复杂
CSV(逗号分隔值)是交换表格数据最常用的格式之一。它用于从Excel、Google Sheets、数据库和简单日志中导出数据。在Swift生态系统(iOS、macOS、watchOS、tvOS)中,没有内置的CSV处理模块,但有几个经过验证的库可以大大简化这一过程。在本文中,我们将介绍最佳工具并编写几个代码示例。
为什么不应该手动编写CSV解析器?
乍一看,CSV似乎很简单:按逗号分割字符串就完成了。然而,在实践中会遇到一些复杂情况:
- 字段可能包含逗号(例如,
"Smith, John")。 - 字段可能被引号包裹,而引号内部可能包含转义引号(
"")。 - 不同系统使用不同的分隔符(逗号、分号、制表符)。
- 编码问题(UTF-8、UTF-16、Windows-1251)。
因此,对于生产代码,强烈建议使用现成的库。
Swift中最佳的CSV库
1. SwiftCSV(作者:Naoto Kaneko)
最流行且轻量级的库之一。支持读取和写入,自动处理引号和转义。通过Swift Package Manager(SPM)和CocoaPods工作。
// 通过SPM集成:.package(url: "https://github.com/naoty/SwiftCSV.git", from: "0.9.0")2. CodableCSV(作者:Dehesa)
一个现代库,与Codable协议集成。允许直接将CSV解析为Swift结构体。非常适合数据具有严格类型的项目。
// 集成:.package(url: "https://github.com/dehesa/CodableCSV.git", from: "0.6.0")3. CSwift
一个简单快速的库,API最小。非常适合小型项目或快速原型开发。
示例1:使用SwiftCSV读取CSV
假设我们有一个文件users.csv:
id,name,email1,伊万·伊万诺夫,ivan@example.com2,玛丽亚·彼得罗娃,maria@example.com3,约翰·多伊,"john.doe@example.com"读取代码:
import SwiftCSV
guard let csvURL = Bundle.main.url(forResource: "users", withExtension: "csv") else { print("文件未找到") return}
do { let csv = try CSV(url: csvURL) // 将行作为字典数组访问 for row in csv.rows { if let id = row["id"], let name = row["name"], let email = row["email"] { print("ID: \\(id), 姓名: \\(name), 邮箱: \\(email)") } } // 或按列访问 print("所有姓名: \\(csv.columns["name"] ?? [])")} catch { print("解析错误: \\(error)")}示例2:使用SwiftCSV写入CSV
import SwiftCSV
let headers = ["姓名", "年龄", "城市"]let rows = [ ["安娜", "28", "莫斯科"], ["鲍里斯", "35", "圣彼得堡"], ["维克多", "22", "新西伯利亚"]]
do { let csv = try CSV(string: "", headers: headers, rows: rows) let csvString = csv.output // 获取CSV字符串 print(csvString) // 保存到文件 let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] let fileURL = documentsPath.appendingPathComponent("output.csv") try csvString.write(to: fileURL, atomically: true, encoding: .utf8) print("文件已保存: \\(fileURL)")} catch { print("写入错误: \\(error)")}示例3:CodableCSV — 解析为结构体
此示例展示了如何轻松地将CSV与数据模型集成:
import CodableCSV
struct User: Decodable { let id: Int let name: String let email: String}\