【问题标题】:How to avoid false separators in csv / XML如何避免 csv / XML 中的错误分隔符
【发布时间】:2016-05-05 13:08:51
【问题描述】:

我一直在尝试了解 XML 和 CSV 解析的工作原理,但实际上还没有编写任何代码。我可能需要在正在进行的项目中解析一个 .csv 文件,我想做好准备。 (我必须将它们转换为 .ofx 文件)

我也知道那里可能有一千个 XLM 和 csv 解析器,所以我比我担心的还要好奇。我打算使用我相信微软提供的XMLReader

假设我有以下 .csv 文件

2016 年 2 月 2 日;我的名字;我的姓 ;某地; 321654;评论;废话

有时会缺少一个字段。这意味着,就示例而言,姓氏不是强制性的,并且某些字段可以紧跟在名字之后。

我的问题是:

  • 如何避免 somefield 和 lastname 之间的混淆?

我可以计算字段的总数,但在我的情况下,两个是可选的,如果只缺少一个,我无法确定是哪一个。

  • 如何避免错误的“标签”?我的意思是,如果用户的第一条评论包含;,我怎么能确定这是他评论的一部分,而不是以下标签的开头?

同样,我可以计算剩余字段并找出我在哪里,但这不包括可选字段问题。

我的问题也适用于 XML,如果用户开始以他的形式编写 XML,我该怎么办?无论我决定将表单导出为 .csv 还是 .xml,都会有问题。

现在我假设 c# Xml 阅读器/解析器足以应付它;如果是的话,我真的很好奇怎么做。

【问题讨论】:

  • 缺少的字段应该仍然有没有数据的分号。 CSV 通常考虑用逗号分隔。您有一个带有分号分隔符的文件。

标签: c# xml parsing csv


【解决方案1】:

假设 CSV/XML 数据已正确导出,这些都不是问题。缺少的字段将由重复的分隔符处理:

02/02/2016;myfirstname;;somefield

字段中的分号通常通过引用来处理:

2016 年 2 月 2 日;“我的名字;姓名”;

引号在字符串中被转义:

2016 年 2 月 2 日;“我的”“名字”;

对于 XML,问题就更小了,因为标签或属性都有名称。

如果您的 CSV 数据格式不正确,那么您的问题就更大了,因为可能无法区分缺失的字段和未加引号的分隔符。

【讨论】:

  • 我明白,这解决了一切,我得到的 .csv 实际上并不是这样形成的。但即使这是一个“大问题”,也很容易解决。谢谢伙计,但现在我意识到我的问题有点毫无意义,因为我是在错误的假设下问的(我的文件很好)
  • 为了完整起见,您可能需要添加:分隔符不应被空格包围(某些解析器可能会遇到问题)。引用字段中的引号必须用另一个引号转义 - 例如:27";monitor 将变为 "27"";monitor"
【解决方案2】:
  1. 如何避免错误的“标签”?如果(可以)包含分隔符,则应引用字符串值。如果您创建 CSV 文件,请引用和取消引用所有字符串值。
  2. 如何避免 somefield 和 lastname 之间的混淆?对此没有通用的解决方案,所有情况都必须一一处理。通用算法可以决定是否缺少名字或姓氏?不。 如果您知道可以省略哪些字段,则可以编写“智能”处理。

使用 XML,所有问题都会迎刃而解。

【讨论】:

    【解决方案3】:

    如何避免 somefield 和 lastname 之间的混淆?

    如果不改变文件的逻辑,就没有办法做到这一点。例如:当“mylastname”为空时,你可能有一个“”值、空字符串或类似的;;

    如何避免错误的“标签”?我的意思是,如果用户的第一条评论包含一个;,我怎么能确定它是他评论的一部分,而不是下面标签的开头?

    很简单,你必须像这样归档:

    ; - 列分隔符

    "" - 列的分隔符

    价值;价值;“价值;;;;价值”;价值

    仅将其拆分为 separtor ;如果没有“”中的分隔符,这段代码会被测试和编译

    public static string[] SplitWithDelimeter(this string line, char separator, char checkSeparator, bool eraseCheckSeparator)
            {
                var separatorsIndexes = new List<int>();
    
                var open = false;
    
                for (var i = 0; i < line.Length; i++)
                {
                    if (line[i] == checkSeparator)
                    {
                        open = !open;
                    }
    
                    if (!open && line[i] == separator )
                    {
                        separatorsIndexes.Add(i);
                    }
                }
    
                separatorsIndexes.Add(line.Length);
    
                var result = new string[separatorsIndexes.Count];
    
                var first = 0;
    
                for (var j = 0; j < separatorsIndexes.Count; j++)
                {
                    var tempLine = line.Substring(first, separatorsIndexes[j] - first);
    
                    result[j] = eraseCheckSeparator ? tempLine.Replace(checkSeparator, ' ').Trim() : tempLine;
    
                    first = separatorsIndexes[j] + 1;
                }
    
                return result;
            }
    

    返回是:

    价值

    价值

    “价值;;;;价值”

    价值

    【讨论】:

      猜你喜欢
      • 2014-10-12
      • 1970-01-01
      • 2013-11-01
      • 2020-05-25
      • 2013-06-29
      • 2011-11-17
      • 2022-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多