Импортировать данные .csv в массив
Я использую Objective-C последние годы.
Теперь я пробую 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?
Есть ли лучшие рекомендации - рекомендации?
Ответы
Ответ 1
Доступно несколько быстрых библиотек:
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, который представляет собой простую библиотеку синтаксического анализа CSV для OSX и iOS.
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, который является парсером csv, соответствующим rfc4180, но, по словам автора, он все в памяти, поэтому не подходит для больших файлов.
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"]
// ]
Ответ 2
Не используйте SwiftCSV в соответствии с самым последним ответом.
SwiftCSV не обрабатывает двойные кавычки прямо сейчас, поэтому, если любые данные в вашем файле CSV имеют разрывы строк или запятые в нем, SwiftCSV не будет работать. И вы можете потратить драгоценное время на разработку, узнав, почему он не работает... чтобы сохранить вас в то время, просто используйте другую библиотеку.
Библиотека CSwiftV отлично работала для меня:
https://github.com/Daniel1of1/CSwiftV
Он обрабатывает цитируемый текст, символы новой строки, запятые, работает как очарование моих данных. Он также имеет модульные тесты и соответствует стандарту rfc4180.
Ответ 3
Каждый ответ требует, чтобы вы установили/загрузили стороннюю утилиту, но это может быть не оптимальным, если файл, с которым вы работаете, чрезвычайно прост или вы работаете в компании, которая ограничивает сторонний код.
Итак, я решил, что просто опубликую невероятно простой, обычный 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. Что-то более сложное, чем это, я рекомендую использовать одну из библиотек, размещенную в других ответах.
Я просто надеюсь, что это поможет кому-то немного набирать текст.
Ответ 4
I рекомендую использовать CSVImporter - он заботится о вещах вроде цитируемого текста (после RFC 4180) для вас и даже без проблем обрабатывает очень большие файлы.
По сравнению с другими решениями он работает как асинхронно (предотвращает задержки), а читает файл 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
}
}
Воспользуйтесь более сложными функциями, такими как сопоставление данных и обратные вызовы:
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
}
}