处理分隔文件的最佳方法


16

因此,通常CSV文件使用逗号和返回字符作为字段和行定界符。

这可能会导致同时包含这两个字符的文本出现明显问题。

显然那里有选择(转义),但是人们如何处理呢?使用不同的字符-管道还是tilda?逃脱他们?毕竟是2010年,现在不使用分隔文件了吗?

至少要努力寻找不出现问题的适当机会。

(请注意,这是出于好奇而不是更扎实的问题-这是我一次又一次地尝试处理数据的问题,总是绕过它,但通常感觉有点好,很脏,并想知道其他人的经历是什么)。


请仔细考虑使用CSV的方法-很好并且易于处理(请参见常见转义规则的答案),但是它互操作性不如应有的可互操作性-如果您只是与自己的程序通信,那很好,但是如果想要导入其他地方会有些奇怪,因为不同的程序遵循不同的转义规则。
迈克尔·科恩

@Michael-绝对。但是,问题在于它无所不在,以至于您几乎总是想出一个非常诱人的选择,而在许多较旧的系统中,这是唯一的选择。
乔恩·霍普金斯

成熟的库以多种语言(某些常见语言)存在,用于读写字符分隔的文件。他们将处理大多数情况。编写自己的CSV解析器似乎是一种常见的反模式。
quentin-starin 2010年

Answers:


13

根据维基百科

带有逗号的字段必须用双引号引起来。

而且:

带有嵌入式双引号字符的字段必须放在双引号字符内,并且每个嵌入式双引号字符必须由一对双引号字符表示。

我不知道是谁发明的,但是它有效地表明了最终您必须逃脱。这是唯一的解决方案。其他所有内容都只是胶带之上:也许现在就可以使用,但是最终您会遇到需要例外的情况,这需要一个例外,而且不久之后您便会陷入困境比简单的转义字符解决方案复杂得多。

似乎CSV的创建者首先尝试通过使用双引号特殊语法来避免转义逗号,该特殊语法允许保存逗号,但是后来有人也想保存双引号字符,因此他们不得不在这一点上进行转义-有趣地使用双引号作为转义字符。如果他们决定首先适当地转义,那么语法现在会更简单。


3
应该是什么,什么是..通常是不同的:)
Tim Post

我认为解决方案还可以。对于简单的数据,CSV做工精细,复杂的数据,则引用是necesary,并逃离“与‘’可以追溯到BASIC。
Ernelli

1
@Ernelli:现在,我考虑得更多,实际上这可能是人类可读性和简单性之间的合理折衷。逃避的问题是,即使计算机解析起来很琐碎,它对人类来说也很难看。因此,仅在极少数情况下保留转义符(“带有嵌入式双引号字符的字段”)会产生通常看起来非常易于理解的输出。假设字段名中的逗号比字段名中的双引号更常用,这是一个很好的解决方案。
Joonas Pulakka 2010年

2

我假设你有这样的事情:

Foo,Baz,,,"Foo,Baz"

如果包含分隔符字符串中没有报价或逃脱,你有没有真正的解析文件的可靠方法。

但是,您可以检查数据以进行分析并得出如下结论:

  • 逗号分隔的浮点数应视为字符串
  • 如果此之前或之后的行包含较少的定界符,请跳过对这一行的分析并记录
  • 像“

您确实必须编写一个解析器来处理类似的事情,但是不必太复杂。

以我的经验,从类似Excel的文件中导入大量转储总是导致不得不回头查看一些奇怪的东西。你的挑战是给你的程序只是有关数据,以便它不会做疯狂的插入足够的常识。然后查看记录的内容并清洗/漂洗/重复。

我曾经为一家使用所有Ubuntu工作站的小公司处理内部常见问题解答。FAQ的一部分给出了“ shell快捷方式”,并以管道分隔符出现在我的脑海中。好吧,答案通常也用竖线分隔(即grep foo | something),并且不加引号或转义。我觉得很痛苦:)


2

CSV到目前为止没有任何问题

CSV适用于严格定义的数据,这些数据不太可能更改格式,并且不会给收件人解析器带来很多惊喜。

以下是一些大陷阱的方便列表:

  1. 在“”内转义“”(字段包含字段定界符)
  2. 包含CRLF的“(字段包含行定界符)
  3. Unicode(基本文本格式可能不足)
  4. 不同操作系统的不同线路终端器(是CR还是CRLF或LF或NUL?)
  5. 内联注释(以#,//,-、;等开头的行)
  6. 版本管理(文件的最新版本包含更多或更少的字段)
  7. 区分NULL和空数据(“””为空,但“,”为空吗?)

您可以通过描述字段解析方式的元数据头来解决这个问题,但是您也可以只使用XML。正是由于这种自由形式的CSV混乱而发明的。XML方法似乎过于繁重,从表面上看,这可能是一个简单的问题。

一种流行的替代方法是“怪异字符分隔符”策略。这可以解决上面的许多转义问题,因为您使用|这样的东西。(管道)字符用于字段定界,CRLF用于记录终止。这不会解决多行字段问题(除非您使用字段计数器),但是您确实可以得到格式正确的人类代码行。

总体而言,如果您只是在寻找一种处理此类文件的简单方法,那么在Java世界中,您可以将OpenCSV扔给它。这样,您就可以将所有问题抽象到已建立的框架中。


2

CSV在许多情况下仍然是一种有效的格式,尤其是因为它仍然是客户写入需要导入到应用程序中的数据的最简单方法。我们的客户中很少有人喜欢处理XML,也许是因为它非常冗长,并且包含所有这些“可怕的”尖括号。对于他们来说,将大脑包绕在一个简单的项目列表(由商定的字符分隔)上,并让他们同意在字段内容中不允许使用同一字符,要简单得多。

也就是说,您仍然必须正确处理输入并检查它们使用无效字符的情况。我已经开始将FileHelpers用于CSV解析需求。


1

我通常会坚持标准并逃避它们。在大多数编程语言中,都有良好的内置支持或良好的库。

取决于使用哪种格式的情况,并且CSV是交换简单数据格式结构的合理格式。


0

忘记CSV,请使用JSON。易于编写,易于解析。XML就是2005年


6
当您要使用属于JSON格式的字符(例如{或)时,会遇到相同的问题
Salandur 2010年

Salandur:一点也不!有逃脱的确切规则!但是{和,甚至不需要转义,因为里面是字符串,所以它们不是模棱两可的!
user281377 2010年

1
很好,但是我不记得excel具有“导出到JSON”功能:)有时候,您必须解析奇怪的东西,即使只是为了使它们变成更可接受的格式。
蒂姆·波斯特

1
JSON能够传递大约一百万个相同形状的对象是如此的出色。等一下。
Frank Shearar 2010年

1
JSON在此问题上没有比CSV有所改进,并且与许多应用程序之间严重缺乏互操作性(如前所述,无法从Office,SQL DB等导入或导出)。JSON非常适合内部轻量级的客户端操作,而XML则更适合在应用程序之间传递数据。
Dan Diplo

0

通常,我发现自己正在得到一个TSV(制表符分隔的值)而不是CSV文件,将文件拉入Emacs并查看它从未使用过的几个不常见字符中的哪一个(在这里,$通常是个不错的选择),然后将所有标签转换为$。

从那里,可以告诉GNU AWK使用$作为字段分隔符,而Bob是您的叔叔。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.