致亲爱的 CSV 格式
A love letter to the CSV format

原始链接: https://github.com/medialab/xan/blob/master/docs/LOVE_LETTER.md

CSV的衰落被严重夸大了。虽然像Parquet这样的新格式提供了一些特定优势,但CSV仍然是一个强大且相关的工具。它的简洁性是关键:格式易于理解和实现,使其具有普遍的可访问性。CSV的开放、非专有特性允许灵活的编码和人工可读性/可编辑性。至关重要的是,它擅长逐行流式处理,能够以最小的内存使用效率处理大型数据集。追加新数据非常简单。CSV的动态类型在不同语言的数据解释中提供了灵活性。它具有自然的简洁性,最大限度地减少了开销。一个独特的特性是反向CSV仍然是有效的CSV,这有助于高效读取最后几行并实现无缝的流程恢复。这些经常被忽视的优势巩固了CSV作为一种强大而有价值的数据序列化格式的地位。

一篇题为“致CSV格式的一封情书”的Hacker News帖子引发了讨论。一位评论者指出Excel处理CSV文件时的困难正是CSV固有价值的证明。另一位评论者对Excel无法根据扩展名无缝打开和解释CSV文件表示困惑。第三位用户虽然承认微软格式的挑战,但建议使用Pandoc将复杂的格式(如.docx)转换为易于解析的.html5,以便更容易操作。他们还称赞这篇博文和文中提到的Xan终端工具。
相关文章
  • (评论) 2023-12-31
  • (评论) 2024-02-19
  • (评论) 2024-08-06
  • 了解 Parquet、Iceberg 和 Data Lakehouses 2023-12-31
  • (评论) 2024-07-21

  • 原文

    Or why people pretending CSV is dead are wrong

    Every month or so, a new blog article declaring the near demise of CSV in favor of some "obviously superior" format (parquet, newline-delimited JSON, MessagePack records etc.) find its ways to the reader's eyes. Sadly those articles often offer a very narrow and biased comparison and often fail to understand what makes CSV a seemingly unkillable staple of data serialization.

    It is therefore my intention, through this article, to write a love letter to this data format, often criticized for the wrong reasons, even more so when it is somehow deemed "cool" to hate on it. My point is not, far from it, to say that CSV is a silver bullet but rather to shine a light on some of the format's sometimes overlooked strengths.

    The specification of CSV holds in its title: "comma separated values". Okay, it's a lie, but still, the specification holds in a tweet and can be explained to anybody in seconds: commas separate values, new lines separate rows. Now quote values containing commas and line breaks, double your quotes, and that's it. This is so simple you might even invent it yourself without knowing it already exists while learning how to program.

    Of course it does not mean you should not use a dedicated CSV parser/writer because you will mess something up.

    2. CSV is a collective idea

    No one owns CSV. It has no real specification (yes, I know about the controversial ex-post RFC 4180), just a set of rules everyone kinda agrees to respect implicitly. It is, and will forever remain, an open and free collective idea.

    Like JSON, YAML or XML, CSV is just plain text, that you are free to encode however you like. CSV is not a binary format, can be opened with any text editor and does not require any specialized program to be read. This means, by extension, that it can both be read and edited by humans directly, somehow.

    CSV can be read row by row very easily without requiring more memory than what is needed to fit a single row. This also means that a trivial program that anyone can write is able to read gigabytes of CSV data with only some kilobytes of RAM.

    By comparison, column-oriented data formats such as parquet are not able to stream files row by row without requiring you to jump here and there in the file or to buffer the memory cleverly so you don't tank read performance.

    But of course, CSV is terrible if you are only interested in specific columns because you will indeed need to read all of a row only to access the part you are interested in.

    Column-oriented data format are of course a very good fit for the dataframes mindset of R, pandas and such. But critics of CSV coming from this set of pratices tend to only care about use-cases where everything is expected to fit into memory.

    5. CSV can be appended to

    It is trivial to add new rows at the end of a CSV file and it is very efficient to do so. Just open the file in append mode (a+) and get going.

    Once again, column-oriented data formats cannot do this, or at least not in a straightforward manner. They can actually be regarded as on-disk dataframes, and like with dataframes, adding a column is very efficient while adding a new row really isn't.

    6. CSV is dynamically typed

    Please don't flee. Let me explain why this is sometimes a good thing. Sometimes when dealing with data, you might like to have some flexibility, especially across programming languages, when parsing serialized data.

    Consider JavaScript, for instance, that is unable to represent 64 bits integers. Or what languages, frameworks and libraries consider as null values (don't get me started on pandas and null values). CSV lets you parse values as you see fit and is in fact dynamically typed. But this is as much of a strength as it can become a potential footgun if you are not careful.

    Note also, but this might be hard to do with higher-level languages such as python and JavaScript, that you are not required to decode the text at all to process CSV cell values and that you can work directly on the binary representation of the text for performance reasons.

    Having the headers written only once at the beginning of the file means the amount of formal repetition of the format is naturally very low. Consider a list of objects in JSON or the equivalent in XML and you will quickly see the cost of repeating keys everywhere. That does not mean JSON and XML will not compress very well, but few formats exhibit this level of natural conciseness.

    What's more, strings are often already optimally represented and the overhead of the format itself (some commas and quotes here and there) is kept to a minimum. Of course, statically-typed numbers could be represented more concisely, but you will not save up an order of magnitude there neither.

    8. Reverse CSV is still valid CSV

    This one is not often realized by everyone but a reversed (byte by byte) CSV file, is still valid CSV. This is only made possible because of the genius idea to escape quotes by doubling them, which means escaping is a palindrom. It would not work if CSV used a backslash-based escaping scheme, as is most common when representing string literals.

    But why should you care? Well, this means you can read very efficiently and very easily the last rows of a CSV file. Just feed the bytes of your file in reverse order to a CSV parser, then reverse the yielded rows and their cells' bytes and you are done (maybe read the header row before though).

    This means you can very well use a CSV output as a way to efficiently resume an aborted process. You can indeed read and parse the last rows of a CSV file in constant time since you don't need to read the whole file but only to position yourself at the end of the file to buffer the bytes in reverse and feed them to the parser.

    It clearly means CSV must be doing something right.

    联系我们 contact @ memedata.com