【问题标题】:Funny CSV format help有趣的 CSV 格式帮助
【发布时间】:2009-08-18 04:30:39
【问题描述】:

我收到了一个有趣的 CSV 格式的大文件来解析成数据库。

分隔符是分号 (;)。如果其中一个字段包含分号,则通过用双引号将其“转义”,例如 ";"

我确信永远不会有两个相邻的字段带有尾随/前导双引号,所以这种格式在技术上应该没问题。

现在,我正在考虑用 VBScript 解析它

  1. 用 GUID 替换 ";" 的每个实例,
  2. 用分号将行分割成数组,
  3. 通过阵列返回,将 GUID 替换为 ";"

这似乎是最快的方法。有没有更好的办法?我想我可以使用子字符串,但这种方法似乎是可以接受的......

【问题讨论】:

  • 您打算将此信息存储在您的数据库中吗?
  • 是的——这就是数据的发展方向。
  • 我会指出,CSV 中的 C 代表“逗号”,这不是第一次了 - 如果您的分隔符不是逗号,那么您没有 CSV 数据。
  • 如果数据字段包含" 字符会怎样???
  • 如果您使用其中一种文本处理程序(OLEDB Jet Text 或 ODBC 文本桌面驱动程序),这可以通过使用 schema.ini 文件轻松处理。顺便说一句,我相信逗号是小数点的语言环境,CSV 文件使用分号作为字段分隔符。

标签: parsing vbscript csv


【解决方案1】:

您的方法听起来不错,但需要注意的是,您的 GUID 绝对没有可能出现在文本本身中。

我之前用于此类数据的方法是在分号上拆分,如果两个相邻的字段以引号结尾并以引号开头,则将它们组合起来。

例如:

Pax;is;a;good;guy";" so;says;his;wife.

变成:

0 Pax
1 is
2 a
3 good
4 guy"
5 " so
6 says
7 his
8 wife.

然后,当您发现字段 4 和 5 以引号结束和开始(分别)时,您将字段 4 的结束引号替换为分号并删除字段 5 的开始引号(当然还要加入它们)来组合它们.

0 Pax
1 is
2 a
3 good
4 guy; so
5 says
6 his
7 wife.

【讨论】:

  • 我想世界上一半的软件都是基于 GUID 的非重复的。此外,这些字段不适用于 GUID,因此日常的非实验性/恶意行为不会导致 GUID 被输入。
【解决方案2】:

在伪代码中,给出:

  • input:一个字符串,第一个字符是input[0];最后的 字符是 input[length]。此外,假设一个假人 字符,输入[长度+1]。它可以是任何东西,除了 ;"。该字符串是“CSV”文件的一行。

  • length:正整数,input

  • 中的字符数

这样做:

  • 设置开始 = 0

  • 如果输入[0] = ';':

    • 开头有一个空白字段;用它做任何事

    • 设置开始 = 2

  • endif

  • 对于介于 1 和 length 之间的每个 c

    • 下一次迭代,除非 string[c] = ';'

    • 如果 input[c-1] ≠ '"' 或 input[c+1] ≠ '"':                    // 测试转义序列";"

      • 找到半开范围 [start,c) 的字段组成;做任何事 用它。注意在空字段的情况下,start≥c,离开 一个空范围

      • 设置开始 = c+1

    • endif

  • 结束foreach

当然,未经测试。像这样调试代码总是很有趣……

input[0] 的特殊情况是确保我们永远不会查看 input[-1]。如果您可以使 input[-1] 安全,那么您可以摆脱这种特殊情况。您还可以在 input[0] 中放置一个虚拟字符,然后从 input[1] 开始您的数据和解析。

【讨论】:

    【解决方案3】:

    一种选择是查找正则表达式的实例:

    [^"];[^"]

    然后用子串将字符串分开:

    List<string> ret = new List<string>();
    Regex r = new Regex(@"[^""];[^""]"); 
    Match m;
    
    while((m = r.Match(line)).Success)
    {
        ret.Add(line.Substring(0,m.Index + 1);
        line = line.Substring(m.Index + 2);
    }
    

    (对不起C#,我不知道VBScript)

    【讨论】:

      【解决方案4】:

      .csv 文件使用引号是正常的。如果字段中有引号,那么您可能会看到开头和结尾以及嵌入的引号都连续两三个串在一起。

      【讨论】:

      • 是的,但 CSV 的标准是如果该字段包含分隔符,则将 whole 字段用引号括起来。像这样转义字符是不标准的,我希望我的解析方法足以处理它。
      【解决方案5】:

      如果您使用的是 SQL Server,您可以尝试使用 T-SQL 为您处理一切。

      从 OPENDATASOURCE('Microsoft.JET.OLEDB.4.0', '数据源=F:\MyDirectory;Extended Properties="text;HDR=No"')... [MyCsvFile#csv]

      这将创建并填充“MyTable”。在 SO 上阅读有关此主题的更多信息 here

      【讨论】:

        【解决方案6】:

        我建议使用 RegEx 来分解字符串。

        • 查找每个“;”这不是 “;”并将其更改为其他内容 不会出现在您的字段中。
        • 然后遍历并替换“;”与;

        现在您的字段包含正确的数据。

        大多数进口商可以很容易地换掉分隔符。

        这基本上是您的 GUID 想法。只需在开始之前确保 GUID 对您的文件是唯一的,就可以了。我倾向于开始使用'Z'。获得足够多的“Z”后,您将变得独一无二(有时只需 1-3 个即可)。

        雅各布

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-08
          • 2023-04-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多