【问题标题】:Splitting string on commas when data can contain commas当数据可以包含逗号时,在逗号上拆分字符串
【发布时间】:2011-06-11 07:05:23
【问题描述】:

我有一个 CSV 文件(不是我设计的,我现在无法更改,也永远无法更改),其中包含如下行:

"Surname, Firstname", yes, no, somestring, whatever, etc

正如您在此处看到的,第一个 , 不是我想要拆分字符串的逗号。请注意,这个特殊的逗号包含在引号内。

因此,一个简单的string.split(',') 显然是行不通的,因为它会给我一个长度为 7 的数组,而不是 6。

有没有办法解决这个问题?我正在考虑使用正则表达式来拆分字符串,但我在正则表达式中的能力不足,无法想出一种模式,它只会在不包含在引号内的逗号上进行拆分。

我可以通过逐个字符地读取每个字符串来想出丑陋、骇人的方法,但这必须是最后的手段,因为我确信有更好的方法!

【问题讨论】:

  • 这看起来像来自 Excel 的 .csv。总是很有趣。当数据包含引号和逗号时更有趣......
  • 它实际上不是来自 Excel,但是是的,很有趣! :) 它来自网络上的某个位置,我的程序读取文件并尝试解析它。
  • 一次读取一个字符不一定是丑陋的黑客行为。我建议找一个 C# CSV 解析器,因为我确信这样的东西已经存在了。
  • 作为一个丑陋的 hack 解决方案,您始终可以读取元素的第一个字符,如果它是一个引号,请推进您的计数器并将下一个索引值添加到前一个并继续。
  • +1 @Brian Donovan。如果它不起作用,你的代码有多优雅都没关系。此外,如果值包含 " 字符会发生什么 - 它们是否加倍?逃跑了?

标签: c# regex string


【解决方案1】:

您可以使用TextFieldParser class 轻松处理此问题。只需将 HasFieldsEnclosedInQuotes 设置为 true。

【讨论】:

  • 当这是作为 C# 问题发布时,您引用的是 .NET 4.5 Visual Basic 类。
  • @aggaton 仅仅因为该类型位于 Microsoft.VisualBasic 命名空间中,并不意味着它不能在 C# 中使用。 TextFileParser 在 C# 中工作得很好,它是核心框架的一部分 - 没有理由避免它。
  • @ReedCopsey 是TextFieldParser,但不是TextFileParser。您设法链接到正确的内容,但始终写错。
  • 请注意,HasFieldsEnclosedInQuotes 可能只有在 all 字段用引号括起来时才应该设置。我关闭了他的选项,它在解析 MS Excel 导出时效果很好,其中只有包含引号或逗号的字段被引号包围。
【解决方案2】:

我会建议使用 CSV 解析器库 - 还有其他您不会想到的情况(新行作为引用字段的一部分)。

VisualBasic 命名空间有一个很好的库可以提供帮助 - TextFieldParser

【讨论】:

  • C# 开发人员不应该担心 VisualBasic 命名空间。没有任何意义 IRL,不添加机器上没有的依赖项,等等。
  • 很漂亮,正如@Will 所说,在 C# 中使用时效果很好。为什么微软会在这么奇怪的地方隐藏这样的工具?
【解决方案3】:

我知道这里有很多人认为不应该使用逐个字符的比较并且会强烈反对我,但我不相信像微软这样的公司不是唯一应该这样做的公司编程。

毕竟,Split 会进行逐个字符的比较,那么当您调用不完全符合您要求的现有代码时,为什么它会变得不那么难看?

无论如何,我的方法是编写自己的代码。我已经在http://www.blackbeltcoder.com/Articles/files/reading-and-writing-csv-files-in-c 在线发布了代码。

【讨论】:

  • 谢谢乔纳森。我对如何使用您的代码有点困惑,我不确定为什么需要将参数传递给 ReadRow()?
  • 完美运行!谢谢乔纳森。
  • 很高兴听到它。大多数文章都包含一个演示项目,但没有那个。感谢您让我知道,对于每个人来说,应该如何调用该方法可能并不明显。我会考虑更新它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-28
  • 2014-02-11
  • 1970-01-01
  • 1970-01-01
  • 2015-03-07
  • 1970-01-01
  • 2011-12-25
相关资源
最近更新 更多