我过去几年使用过Objective-C。 现在我用swift尝试Xcode 6 beta 4。
我想将.csv格式导入我的网络服务器。我在Objective-C中的旧代码是:
NSString *stringURL = @"https:// [URL] /versionen/versionen.csv";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSString *csvResponseString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
NSArray *MZVersionDatenZeilen = [csvResponseString componentsSeparatedByString:@"\n"];
NSEnumerator *MZVersionEnumerator = [MZVersionDatenZeilen objectEnumerator];
NSMutableArray *MZVersionDatenArray = [NSMutableArray arrayWithCapacity:[MZVersionDatenZeilen count]];
NSString *MZVersionZeile;
while (MZVersionZeile = [MZVersionEnumerator nextObject])
{
[MZVersionDatenArray addObject:[MZVersionZeile componentsSeparatedByString:@";"]];
}
}
我怎么能在Swift中这样做? 有最佳做法 - 推荐吗?
答案 0 :(得分:13)
有多个swift库可用:
CSVImporter,这是一个适合处理大型csv文件的异步解析器。
let path = "path/to/your/CSV/file"
let importer = CSVImporter<[String]>(path: path)
importer.startImportingRecords { $0 }.onFinish { importedRecords in
for record in importedRecords {
// record is of type [String] and contains all data in a line
}
}
SwiftCSV,这是一个用于OSX和iOS的简单CSV解析库。
let csvURL = NSURL(string: "users.csv")!
var error: NSErrorPointer = nil
let csv = CSV(contentsOfURL: csvURL, error: error)
// Rows
let rows = csv.rows
let headers = csv.headers //=> ["id", "name", "age"]
let alice = csv.rows[0] //=> ["id": "1", "name": "Alice", "age": "18"]
let bob = csv.rows[1] //=> ["id": "2", "name": "Bob", "age": "19"]
// Columns
let columns = csv.columns
let names = csv.columns["name"] //=> ["Alice", "Bob", "Charlie"]
let ages = csv.columns["age"] //=> ["18", "19", "20"]
和CSwiftV,这是符合rfc4180规范的csv解析器,但据作者说,它全部在内存中,因此不适合大文件。
let inputString = "Year,Make,Model,Description,Price\r\n1997,Ford,E350,descrition,3000.00\r\n1999,Chevy,Venture,another description,4900.00\r\n"
let csv = CSwiftV(String: inputString)
let headers = csv.headers // ["Year","Make","Model","Description","Price"]
let rows = csv.rows
// [
// ["1997","Ford","E350","descrition","3000.00"],
// ["1999","Chevy","Venture","another description","4900.00"]
// ]
答案 1 :(得分:11)
每个答案都要求您安装/下载第三方实用程序,但如果您使用的文件非常简单,或者您在限制第三方代码的公司工作,那么这可能不是最佳选择。
所以我想我会发布令人难以置信的基本的常规CSV文件处理代码,人们可以将其作为基础并根据需要进行简单的CSV处理。
do {
let file = try String(contentsOf: fileUrl)
let rows = file.components(separatedBy: .newlines)
for row in rows {
let fields = row.replacingOccurrences(of: "\"", with: "").components(separatedBy: ",")
print(fields)
}
} catch {
print(error)
}
这将处理您知道没有引号和逗号作为字段内容的一部分的任何CSV文件,在我的情况下是大多数CSV文件。比这更复杂的东西,我建议使用其他答案中发布的一个库。
我希望这可以节省一些人的打字。
答案 2 :(得分:9)
根据当前最受欢迎的答案,不要使用SwiftCSV。
SwiftCSV目前不处理双引号,因此如果CSV文件中的任何数据中包含换行符或逗号,则SwiftCSV将无效。你可能会浪费宝贵的开发时间来找出它无法正常工作的原因......为了节省你的时间,只需使用另一个库。
CSwiftV 库对我来说效果非常好: https://github.com/Daniel1of1/CSwiftV
它处理引用的文本,换行符,逗号,就像我的数据上的魅力一样。它还具有单元测试并符合rfc4180标准。
答案 3 :(得分:3)
我建议使用CSVImporter - 它为您处理引用文字(在RFC 4180之后),甚至处理非常大的文件没有问题。
与其他解决方案相比,它可以同时异步(防止延迟)和逐行读取CSV文件,而不是将整个String加载到内存中(防止内存问题) 。最重要的是,易于使用并提供美丽的回调,用于指示失败,进度,完成甚至数据映射,如果您愿意的话。
最简单的使用方法就是这个(给你每一行作为一个字符串数组):
let path = "path/to/your/CSV/file"
let importer = CSVImporter<[String]>(path: path)
importer.startImportingRecords { $0 }.onFinish { importedRecords in
for record in importedRecords {
// record is of type [String] and contains all data in a line
}
}
利用更复杂的功能,例如数据映射和进度回调:
let path = "path/to/Hogwarts/students"
let importer = CSVImporter<Student>(path: path)
importer.startImportingRecords { recordValues -> Student in
// define your data mapping here
return Student(firstName: recordValues[0], lastName: recordValues[1])
}.onProgress { importedDataLinesCount in
// use this to indicate progress
print("\(importedDataLinesCount) lines were already imported.")
}.onFinish { importedRecords in
for student in importedRecords {
// now importedRecords is an array of Student objects
}
}