在swift中解析CSV文件

时间:2015-06-18 10:40:00

标签: ios swift parsing csv

我在github的帮助下将数据从csv文件解析为字典 解析后我得到这种类型的字典: -

{{#my-component}}
  {{link-to 'MyLinkText' 'my-route-name.sub-route'}}
{{/my-component}}

如何将其转换为简单字典。我需要这样的数据" company_id" =" 1"

谢谢

3 个答案:

答案 0 :(得分:6)

使用 CSwiftV 解析器:https://github.com/Daniel1of1/CSwiftV

它实际上处理引用的文本,因此它处理文本中的换行符和逗号。 SwiftCSV花了我一些时间,因为它没有处理。但我确实了解了CSV格式并对其进行了解析;)

答案 1 :(得分:5)

建议使用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
    }
}

利用更复杂的功能,例如标题结构支持:

// given this CSV file content
firstName,lastName
Harry,Potter
Hermione,Granger
Ron,Weasley

// you can import data in Dictionary format
let path = "path/to/Hogwarts/students"
let importer = CSVImporter<[String: String]>(path: path)
importer.startImportingRecords(structure: { (headerValues) -> Void in

    // use the header values CSVImporter has found if needed
    print(headerValues) // => ["firstName", "lastName"]

}) { $0 }.onFinish { importedRecords in

    for record in importedRecords {
        // a record is now a Dictionary with the header values as keys
        print(record) // => e.g. ["firstName": "Harry", "lastName": "Potter"]
        print(record["firstName"]) // prints "Harry" on first, "Hermione" on second run
        print(record["lastName"]) // prints "Potter" on first, "Granger" on second run
    }
}

答案 2 :(得分:0)

将CSV解析为字符串(行和列)的二维数组

func parseCsv(_ data: String) -> [[String]] {
    // data: String = contents of a CSV file.
    // Returns: [[String]] = two-dimension array [rows][columns].
    // Data minimum two characters or fail.
    if data.count < 2 {
        return []
    }
    var a: [String] = [] // Array of columns.
    var index: String.Index = data.startIndex
    let maxIndex: String.Index = data.index(before: data.endIndex)
    var q: Bool = false // "Are we in quotes?"
    var result: [[String]] = []
    var v: String = "" // Column value.
    while index < data.endIndex {
        if q { // In quotes.
            if (data[index] == "\"") {
                // Found quote; look ahead for another.
                if index < maxIndex && data[data.index(after: index)] == "\"" {
                    // Found another quote means escaped.
                    // Increment and add to column value.
                    data.formIndex(after: &index)
                    v += String(data[index])
                } else {
                    // Next character not a quote; last quote not escaped.
                    q = !q // Toggle "Are we in quotes?"
                }
            } else {
                // Add character to column value.
                v += String(data[index])
            }
        } else { // Not in quotes.
            if data[index] == "\"" {
                // Found quote.
                q = !q // Toggle "Are we in quotes?"
            } else if data[index] == "\r" || data[index] == "\r\n" {
                // Reached end of line.
                // Column and row complete.
                a.append(v)
                v = ""
                result.append(a)
                a = []
            } else if data[index] == "," {
                // Found comma; column complete.
                a.append(v)
                v = ""
            } else {
                // Add character to column value.
                v += String(data[index])
            }
        }
        if index == maxIndex {
            // Reached end of data; flush.
            if v.count > 0 || data[data.index(before: index)] == "," {
                a.append(v)
            }
            if a.count > 0 {
                result.append(a)
            }
            break
        }
        data.formIndex(after: &index) // Increment.
    }
    return result
}

在上方调用CSV数据

let dataArray: [[String]] = parseCsv(yourStringOfCsvData)

然后提取标题行

let dataHeader = dataArray.removeFirst()

我假设您想要一个字典数组(大多数电子表格数据包括多行,而不仅仅是一行)。下一个循环就是为此。但是,如果您只需要将单个行(以及键的标题)放入单个字典中,则可以在下面进行学习,并获得有关如何到达那里的想法。

    var da: [Dictionary<String, String>] = [] // Array of dictionaries.
    for row in dataArray {
        for (index, column) in row.enumerated() {
            var d: Dictionary<String, String> = Dictionary()
            d.updateValue(column, forKey: dataHeader[index])
            da.append(d)
        }
    }
相关问题