CSV格式

**逗號分隔值**（Comma-Separated Values，**CSV**，有時也稱為**字元分隔值**，因為分隔字元也可以不是逗號），其檔案以純文字形式儲存表格資料（數字和文字）。純文字意味著該檔案是一個字元序列，不含必須像二進位數字那樣被解讀的資料。CSV 檔案由任意數目的記錄組成，記錄間以某種換行符分隔；每條記錄由欄位組成，欄位間的分隔符是其它字元或字串，最常見的是逗號或制表符。通常，所有記錄都有完全相同的欄位序列。

CSV 檔案的格式不存在通用標準，也沒有指定所使用的字元編碼，但是在 RFC 4180 中有基礎性的描述，
而 7-bit ASCII 是最基本的通用編碼。

## 用法

CSV 是一種通用的、相對簡單的檔案格式，被使用者、商業和科學廣泛應用。最廣泛的應用是在程式之間轉移表格資料，而這些程式本身是在不相容的格式上進行操作的（往往是私有的和 / 或無規範的格式）。因為大量程式都支援某種 CSV 變體，至少是作為一種可選擇的輸入 / 輸出格式。

例如，一個使用者可能需要交換資訊，從一個以私有格式儲存資料的資料庫程式，到一個資料格式完全不同的電子試算表。最可能的情況是，該資料庫程式可以匯出資料為「CSV」，然後被匯出的 CSV 檔案可以被電子試算表程式匯入。

「CSV」不是一種單一的、定義明確的格式（儘管 RFC 4180 有一個被廣泛使用的定義），因此在實踐中，術語「CSV」泛指具有下列特徵的任何檔案：

1. 純文字，使用某個字元集，比如 ASCII、Unicode、EBCDIC 或 GB2312（簡體中文環境）等；
2. 由記錄組成（典型的是每行一條記錄）；
3. 每條記錄被分隔符分隔為欄位（典型分隔符有逗號、分號或制表符；有時分隔符可以包括可選的空格）；
4. 每條記錄都有同樣的欄位序列。

在這些常規的約束條件下，存在著許多 CSV 變體，故 CSV 檔案不完全相容。然而，這些差異非常小，而且有許多應用程式可以讓使用者預覽檔案（這是可行的，因為它是純文字），甚至指定分隔符、跳脫規則等。如果一個特定 CSV 檔案的差異過大，超出了特定接收程式的支援範圍，那麼可行的做法通常是人工檢查並編輯檔案，或通過簡單的程式來修復問題。

## 歷史

逗號分隔值是一種資料格式，列表方式（「自由形式」）輸入 / 輸出被定義在 FORTRAN 77（77 代表 1977 年）中。列表方式的輸入使用了逗號和 / 或空格作為分隔符，所以用來結束引文的字串不能包含逗號或空格。

相對於固定列寬資料格式，逗號分隔值的列表不僅輸入（例如輸入到打孔卡）更加方便，而且當一個值被錯打一列時也不容易產生錯誤結果。

**逗號分隔列**（CSL）是一種資料格式，起初在最古老的簡單電腦中被稱為**逗號分隔值**（CSV）。在個人電腦（當時更普遍地被稱為「家用電腦」）產業，一個常見的應用是，小企業使用模板和郵寄清單生成推銷郵件。

CSL/CSV 被用來作為簡單的資料庫。一些早期的軟體應用，比如文書處理器，允許一系列「變數資料」在兩個檔案之間被合併：一個是模板檔案，一個是包含姓名、位址和其它資料欄位的 CSL 資料庫。許多應用程式仍然有這種能力。

逗號分隔列過去和現在都被用於在兩個不同架構的機器之間交換資料庫資訊。純文字的 CSV 檔案大幅避免了不相容性，比如位元組順序和字長。這些檔案大部分是可讀的，所以在沒有完美的文件或通訊的情況下仍然很容易處理。

## 常規功能

CSV 格式最好被用來表現記錄集合或序列，其中的每條記錄都有完全相同的欄位序列。這相當於關聯式資料庫中一個單一的關係，或者典型的電子試算表中的資料（雖然不能計算）。

CSV 格式沒有被限定於某個特定字元集。不管用 Unicode 還是用 ASCII，都沒有問題（儘管特定程式支援的 CSV 可能會有它們自己的局限性）。和大部分的私有資料格式不同，CSV 檔案可以從一個字元集翻譯到另外一個字元集。然而，CSV 不提供任何途徑來表明使用的是什麼字元集，所以必須另外通訊，或在接收結束時指出（如果可能）。

如前所述，包含多個關係的資料庫不能匯出為單一的 CSV 檔案。最多，只能添加更多的標識約定，例如標識和分隔不同的關係。這種標識並不難於設計和實現，但是因為沒有這方面的約定，所以基本不具備可移植性。

同樣地，CSV 本身不能表達分層級的或物件導向的資料庫或其它資料。這是因為每一條 CSV 記錄都應當有同樣的結構。CSV 因此基本不適用於文件，比如由 HTML、XML 或者其它的標記式語言或文書處理技術建立的。

欄位會變化的統計資料庫往往有著類似關係的結構，但是會有一些欄位組是可重複的。例如，健康資料庫如人口與健康調查，對於一名給定的父母會為每個孩子重複一些問題（也許直到某個確定的最大的孩子數目）。統計分析系統往往包含可以「旋轉」這類資料的工具：例如，一條包含 5 個孩子資訊的「父母」記錄，可以被分解為 5 條單獨的記錄，每條記錄包含（a）一個孩子的資訊，和（b）一份所有未指定孩子的資訊的拷貝。CSV 可以用「橫的」或「豎的」形式來表達這類資料。

在關聯式資料庫中，類似的問題很容易解決 —— 為每個類似的組另外建立一個關係，並使用外來鍵（如父母的身分證號或名字）將「孩子」記錄與相關的「父母」記錄連接起來。在標記式語言如 XML 中，這類組會被包含在一個容器中（例如，`<child>`），然後按照需要重複該容器。對於 CSV，則尚無被廣泛接受的單檔案解決方案。

## 缺乏規範

「CSV」這個名字表示是用逗號來分隔資料欄位的。然而，「CSV」這個術語還被廣泛用於形式各異的一系列格式。例如，許多所謂的「CSV」檔案實際上使用制表符代替逗號（這種檔案可以更精確地被稱為「TSV」，即制表符分隔值，Tab-Separated Values）；一些實現允許或要求使用單引號或雙引號來包裹某些或全部欄位；還有一些實現保留最前面的一條記錄作為表頭來包含欄位名序列。

其它的實現差別包括如何處理更多常見的欄位分隔符（比如空格或分號）和在文字欄位中的換行符。更加微妙的是對一個空行的翻譯：寫一條零欄位的記錄，或者一條有一個零長度欄位的記錄同樣可以得到這樣的結果；因此對它的解碼是有歧義的 —— 只不過這種歧義通常無傷大雅。

RFC 4180 所記載的標準可以使 CSV 交換簡單化。然而，這一標準僅指定了對基於文字的欄位的處理。對各個欄位的文字的翻譯仍然是由參照程式指定的。特別地，並沒有標準來指定如何表示小數，儘管它們普遍被嵌入在 CSV 資料中，並且一些國家使用點作為小數分隔符，一些國家使用逗號。例如，法文 CSV 檔案可能將圓周率的近似值寫為 3,14159。

一個通用的（如果技術上不令人滿意）互操作性解決方案是依賴人工介入：因為 CSV 檔案是純文字，使用者可以通過使用文字編輯器輕易預覽和診斷絕大部分（如果不是全部）問題。這樣做的例子包括 Microsoft Access 等（關係）資料庫產品，其在匯入 CSV/TSV 這種資料時便允許使用者一邊預覽一邊調整諸如表頭行、分隔符之類的選項。

## 進行中的標準化

「CSV」格式中大量變體的存在說明並沒有一個「CSV 標準」。在常見用法中，幾乎任何定界符分隔的文字資料都可以被統稱為「CSV」檔案。不同的 CSV 格式可能不會相容。

不過，RFC 4180 是一個將 CSV 正式化的努力。它定義了網際網路媒體類型「text/csv」，並且採用它的規則的 CSV 檔案將會具有廣泛的可移植性。它有如下要求：

* 以（CR/LF）字元結束的 DOS 風格的行（最後一行可選）。
* 一條可選的表頭記錄（沒有可靠的方式來檢測它是否存在，所以匯入時必須謹慎）。
* 每條記錄「應當」包含同樣數量的逗號分隔欄位。
* 任何欄位都_可以_被包裹（用雙引號）。
* 包含換行符、雙引號和 / 或逗號的欄位_應當_被包裹。（否則，檔案很可能不能被正確處理）。
* 欄位中的一個（雙）引號字元必須被表示為兩個（雙）引號字元。

這個格式很簡單，可以被大部分聲稱可以讀取 CSV 檔案的程式處理。例外是（a）程式可以不支援在被包裹的欄位中換行，（b）程式可以將可選的表頭當作資料，或者將第一個資料行當作可選的表頭。

## 技術背景

該格式可以追溯至早期的商用電腦，它被廣泛用於在電腦間傳遞資料，這些電腦可能會有不同的內在字長，需要不同的資料格式，等等。為此，CSV 檔案在所有電腦平台上通用。

CSV 是一種分隔的文字檔案，它使用逗號來分割值（許多 CSV 匯入 / 匯出工具的實現也允許使用其它的分隔符）。簡單的 CSV 實現可以禁止欄位值中包含逗號或其它特殊字元如換行符。更複雜的 CSV 實現允許這些特殊字元，它們往往要求用 "（雙引號）包裹這些包含保留字元（如逗號、雙引號或不太通用的換行符）的數值。被嵌入的雙引號字元可以用連續兩個雙引號來表示（Creativyst 2010），或者使用跳脫字元如反斜槓（例如在 Sybase Central 中）。

在電腦科學術語中，CSV 檔案可以被認為是一個「平面檔案資料庫」。

## 基本規則及舉例

存在許多描述「CSV」格式的非正式檔案。IETF RFC 4180（如上所述）定義了格式「text/csv」網際網路媒體類型，並已註冊於 IANA。（Shafranovich 2005）另一個相關規範由含欄位文字提供。Creativyst (2010) 提供了一個概述，說明了在最廣泛使用的應用程式中所使用的變體，並解釋了 CSV 怎樣才能最好地被使用和支援。

這些和其它「CSV」規範及實現的典型規則如下：

* **CSV** 是一種被分隔的資料格式，它有被逗號字元分隔的欄位 / 列和以換行結束的記錄 / 行。
* CSV 檔案不要求特定的字元編碼、位元組序或行結束符格式（某些軟體不支援所有行結束變體）。
* 一條記錄結束於行結束符。然而，行結束符可能被作為資料嵌入到欄位中，所以軟體必須辨識被包裹的行結束符（見下述），以便從可能的多行中正確組裝一條完整的記錄。
* 所有記錄應當有相同數目、相同順序的欄位。
* 欄位中的資料被翻譯為一系列字元，而不是一系列位元或位元組（見 RFC 2046，section 4.1）。例如，數值量 65535 可以被表現為 5 個 ASCII 字元「65535」（或其它形式如「0xFFFF」、「000065535.000E+00」等等）；但不會被作為單個二進位整數的 2 位元組序列（而非兩個字元）來處理。如果不遵循這個「純文字」的慣例，那麼該 CSV 檔案就不能包含足夠的資訊來正確地翻譯它，該 CSV 檔案將不大可能在不同的電腦架構間正確傳遞，並且將不能與 _text/csv_ MIME 類型保持一致。
* 相鄰欄位必須被單個逗號分隔開。然而，「CSV」格式在分隔字元的選擇上變化很大。特別是在某些區域設定中逗號被用作小數點，則會使用分號、制表符或其它字元來代替。

```
1997,Ford,E350
```

* 任何欄位都_可以_被_包裹_（使用雙引號字元）。某些欄位_必須_被包裹，詳見後續規則。

```
"1997","Ford","E350"
```

* 如果欄位包含被嵌入的逗號，必須被包裹。

```
1997,Ford,E350,"Super, luxurious truck"
```

* 每個被嵌入的雙引號字元必須被表示為兩個雙引號字元。

```
1997,Ford,E350,"Super, ""luxurious"" truck"
```

* 如果欄位包含被嵌入的換行，必須被包裹（然而，許多簡單的 CSV 實現不支援欄位內換行）。

```
1997,Ford,E350,"Go get one now
they are going fast"
```

* 在某些 CSV 實現中，起頭和結尾的空格和制表符被截掉。_這一實踐是有爭議的，也不符合 RFC 4180。RFC 4180 聲明「空格被看作欄位的一部分，不應當被忽略。」_ 。

```
1997, Ford, E350
not same as
1997,Ford,E350
```

* 然而，該 RFC 並沒有說當空白字元出現在被包裹的值之外該如何處理。

```
1997, "Ford" ,E350
```

* 在截掉起頭和結尾空格的 CSV 實現中，將這種空格視為有意義資料的欄位必須被包裹。

```
1997,Ford,E350," Super luxurious truck "
```

* 第一條記錄可以是「表頭」，它在每個欄位中包含列名（並沒有可靠途徑來告知一個檔案是否這樣包含表頭；然而，一般在列名中僅使用字母、數字和底線，而不使用其它字元）。

```
Year,Make,Model
1997,Ford,E350
2000,Mercury,Cougar
```

### 舉例

以上資料表可以以 CSV 格式表示如下：

```
Year,Make,Model,Description,Price
1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture ""Extended Edition""","",4900.00
1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00
1996,Jeep,Grand Cherokee,"MUST SELL!
air, moon roof, loaded",4799.00
```

美國 / 英國的 CSV 檔案（小數點是點，值分隔符是逗號）舉例：

```
Year,Make,Model,Length
1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38
```

德國和荷蘭同樣的 CSV/DSV 檔案（小數點是逗號，值分隔符是分號）舉例：

```
Year;Make;Model;Length
1997;Ford;E350;2,34
2000;Mercury;Cougar;2,38
```

後者的格式是不遵循 RFC 4180 的。若要使它遵循，可以使用逗號代替分號作為分隔符，或者使用小數點表示法的國際符號，或者包裹所有包含小數點的數字。

## 應用程式支援

CSV 檔案格式非常簡單，被幾乎所有的電子試算表和資料庫管理系統支援。許多程式語言都有可利用的庫來支援 CSV 檔案。許多實現都支援變換欄位分隔字元和一些包裹約定以最大化接收者處理資料的機會，儘管使用最簡單的約定是最安全的。

Microsoft Excel 會打開.csv 檔案，但依賴於系統的地區設定，它可以使用分號作為分隔符來代替逗號，這是由於在某些語言中逗號被用作小數點。並且，Excel 的許多地區版本不能在 CSV 中處理 Unicode。當遇到這種困難時，一個簡單的解決方案是將副檔名從 `.csv` 變為 `.txt`；然後從一個已經執行的 Excel 中用「打開」命令打開檔案。

當貼上文字資料到 Excel 中時，通常制表符被用作分隔符：如果你複製「hello<tab>goodbye」到剪貼簿中並把它貼上到 Excel 中，它會進入到兩個儲存格中。「hello,goodbye」貼上進 Excel 會進入一個儲存格中，包括逗號。如果您在 Excel 中使用「文字到列」功能並且改變設定，它同樣為貼上進文字資料改變設定。

OpenOffice.org Calc 和 LibreOffice Calc 處理 CSV 檔案，並且通過一個_文字匯入_對話方塊貼上文字，對話方塊要求使用者自己指定分隔符、編碼、列格式等。

在類 Unix 系統上，有許多工具程式至少可以處理某些 CSV 檔案。許多此類工具有辦法改變分隔字元，但是很少能支援任何其它變體（或 Unicode）。這些可用的程式有：

* column
* cut
* paste
* join
* sort
* uniq（-f 來跳過比較前 N 個欄位）

## 參見

* 資料序列化格式比較
* CSV 應用程式支援
* 定界符分隔值
* 含欄位文字
* 制表符分隔值

## 註釋

## 參考資料

## 外部連結

* B2B（商業對商業）應用的 CSV-1203 檔案格式規範（英文）
* 如何：逗號分隔值（CSV）檔案格式 （頁面存檔備份，存於網際網路檔案館）（英文）
* RFC 4180：CSV 檔案格式的 RFC 規範（英文）