首页 > 解决方案 > 在 Swift 中解码/解析 CSV 和类似 CSV 的文件

问题描述

我将不得不编写一个非常定制的类似 CSV 的解析器/解码器。我在 Github 上寻找过开源的,但没有找到适合我需要的。我可以解决这个问题,但我的问题是,在 Swift 中将其实现为 TopLevelDecoder 是否会完全违反键/值解码。

我有键,但不完全是键/值对。在 CSV 文件中,每列数据都有一个键,

我需要解析的文件有很多问题:

  1. 逗号不仅用于分隔字段,而且在某些字段中也有逗号。例子:
//If I convert to an array
Struct Family {
    let name: String?
    let parents: [String?]
    let siblings: [String?]
}

在这个例子中,父母双方的名字在同一个字段中,需要转换为数组,兄弟字段也是如此。

"Name", "Parents","Siblings"
"Danny", "Margaret, John","Mike, Jim, Jane"

在父母的情况下,我可以将其拆分为结构中的两个字段,例如

Struct Family {
    let name: String?
    let mother: String?
    let father: String?
}

但是 Siblings 字段不起作用,因为可以有从零到多个兄弟姐妹。因此我将不得不使用一个数组。

不过,在某些情况下,我会分成两个领域。

  1. 我需要解析的所有文件都不是严格的 CSV。所有文件都有表格数据(逗号或制表符分隔),但有些文件有几行我需要考虑的注释(有时包含元数据)。这些文件具有 .txt 扩展名,而不是 .csv。
## File generated 2020-05-02
"Name", "Parents","Siblings"
"Danny", "Margaret, John","Mike, Jim, Jane"

因此,我需要查看第一行以确定是否有此类注释,在解析完之后,我可以继续将文件的其余部分视为 CSV。

从应用程序的角度来看,我计划让它看起来像任何解码器,但在我的解码器内部,我可以处理它们就像键/值对一样的事情,因为只有一组键,这是第一行在文件中,如果开头没有注释。不过,我仍然想使用 CodingKeys。

你觉得呢?你有没有什么想法?我应该作为解码器实现(实际上是 Swift 中的 TopLevelDecoder),还是滥用键/值解码的想法?另一种方法是将其实现为解析器,但我必须处理几种类型的文件(JSON、GraphQL、CSV 和类似 CSV 的文件),我认为如果我可以对所有人使用解码器,我的应用程序代码会简单得多文件的类型。

对于 JSON 没有问题,因为 Swift 中已经有一个 HSON 解码器。对于 GraphQL 来说,这也不是问题,因为我可以编写一个带有无键容器的解码器。问题文件是那些 CSV 和类似 CSV 的文件。

其中一些将所有内容都用双引号括起来,但对于 CSV 标头中的“键”和值。有些只有键的双引号,而不是值的双引号。有些有逗号分隔的字段,有些是制表符分隔的。有些字段中有逗号,需要特殊处理。在将文件的其余部分解析为 CSV 之前,有些在文件的开头有注释,需要跳过这些注释。

有些文件在第一列中有两个字段。我对这些文件的格式没有任何影响,所以我只需要处理它。

如果您想知道它们是什么文件,我可以告诉您它们是原始 DNA 文件,具有 DNA 匹配的文件,具有与我有匹配 DNA 的人的共同 DNA 片段的文件。这是来自几家 DNA 检测公司的一些略有不同的文件。我希望他们都以标准格式使用 JSON,其中所有密钥也是所有公司的标准格式。但它们都有不同的 CSV 标头和其他差异。

我还必须解码 Gedcom 文件,其中也有键/值编码对,但这种格式也不符合文件中的纯键/值编码。

ALso:我已经搜索过其他有类似问题的人,但不完全相同,所以我不想劫持他们的线程。请参阅此线程建议从 CSV > JSON > Swift 对象

那更多的是如何从 CSV 转换为 JSON,然后再转换为 Swift 中的内部数据结构的问题。我知道我可以编写一个解析器来解决这个问题,但我认为用解码器处理所有这些文件会更优雅,但我想请你考虑一下。

我也想过制定一个新协议

protocol ColumnCodingKey: CodingKey {
)

如果有的话,我还没有决定在协议中包含什么。它可以通过像示例中那样将其留空,然后让我的解码器符合它来工作,那么它可能不会对键/值解码造成很大的违反。

提前致谢!

标签: swiftcsvparsingdecodingkey-value-coding

解决方案


CSV 文件可以使用正则表达式进行解析。为了让您开始,这可能会节省一些时间。很难知道你真正需要什么,因为看起来有很多不同的场景,它可能会发展到更多的情况?

解析 CSV 文件中的一行的正则表达式可能看起来像这样
(?:(?:"(?:[^"]|"")*"|(?<=,)[^,]*(?=,))|^[^,]+|^(?=,)|[^,]+$|(?<=,)$)

这是有关它如何与 javascript 示例一起使用的详细说明 构建 CSV 解析器


推荐阅读