CSVの国際標準 RFC 4180 と JSONの国際標準 RFC 8259 をいまさら読みなおしてみた(前編)


こんにちは。システム開発グループの小田切と申します。

 プログラム実装に関わっていて、JSON*1フォーマットを扱うことが多くなっています。

 そういえば、エイッとなんとなく作るJSONフォーマット*2ですが、今一度、JSONの国際標準を確認してみようと思います。
 そ。の。ま。え。に。

 JSON以前に存在する皆さんに更になじみの深いCSV*3も、いまだに多用しています。まずは、CSVの国際標準を、過去の体験談なども交えて、書きたいと思います。

 CSVの国際標準 RFC 4180

 CSV型の歴史は古く1972年頃から存在していたようで、CSVの名称は1983年からとのことです*4

 私がまともにCSVデータフォーマットに取り組んだのは、昭和の終わりから平成に入る頃でした。当時、まだ学生でアルバイト先としてある情報会社のお手伝いをしていました。Macintosh Plusというアップルのパーソナルコンピュータが出てきて、流行っていました。確か、Mac上のMicrosoft-Excel(以下Excel)やFileMakerⅡなどを使っていました。Excel上のデータを別のソフトウェアに持っていく際、様々な編集・項目追加が必要となりました。そこで、Excel上のデータをCSVにした後、自分がC*5で作ったMac上のプログラムに読込ませることにしました。その際に、データの分離が必要だったのが、CSVフォーマットとの最初の出会いだったかと思います。

 当時は、パソコン通信がやっとでインターネットで自由に検索などなく、CSVの出力仕様は自分で実験してルールを把握するしか方法を考えつかなかったです。EXCELに文字列を打込んでCSV形式で保存し、結果がどうなっているか解析して自分のプログラムの整合性を合わせていました。

 就職してからも国際標準がどこにあるのか判りませんでした*6。2000年代に入ってオープン系ソフトウェア開発に携わり、インタネット関係の仕様として、RFC(Request for Comments)4180に規定されているらしいと雑誌で知りました。2005年とのこと。出版物として取寄せられそうだが、自腹で海外とのやり取りは面倒と諦めていました。それが今では、インターネット上で無料で手に入ります。この点では、本当に良い世の中になりました。今回の入手先は、こちらhttps://tools.ietf.org/pdf/rfc4180.pdfです。 表紙と参考文献含め8ページです。

RFC 4180の内容とは

 では、早速RFC 4180の内容を確認しましょう。私が気になるところを抜粋して気付いた事を書きたいと思います。4節以降はタイトルだけにして内容を省略します。直訳というよりは意訳にしてみました。

原文の和訳/意訳の箇所はこのように枠で囲みます。私の言葉で書いたので誤訳していたらごめんなさい。うまく訳せないところは[  ]で囲み原文の英語をイタリック書式で入れています。
更に囲まれたここには、ドキュメント上のサンプルを記載します。

トップページ

 このドキュメントの作成者は、Y. Shafranovichさんで SolidMatrix Technologies, Inc. の方です。前述のように2005年10月に作成されています*7。このメモの位置付けとして、

インターネットコミュニティに情報を提供する。インターネットの標準仕様は何ら定めるものではない。このメモの配布に制限はない。

とありました。お陰でこのブログが書けます。著作権表示についての記述はあるので、そのまま転記します。

Copyright Notice
   Copyright (C) The Internet Society (2005).

 次回のJSONでは、とっても長くなっています。お楽しみ(?)に。

1. Introduction(はじめに)

 CSV(カンマ区切り値)は頻繁に様々なスプレッドシートプログラム間でデータの交換や変換に使用されている。驚くことに、このフォーマットはとても一般的である一方、公式に文章化されていない。更に、IANA MIMEには、"text/tab-separated-values"(タブ区切り値)は登録されているが、CSVの登録がされていない。それと同時にこのフォーマットに対して、様々なプログラムやOSで異なったMIMEタイプが使用されている。このRFCでは、CSVファイルのフォーマットと、公式に"text/csv" MIMEタイプをRFC 2048として文章化する。

 世の中でCSVの標準はどうなっているのか、文章化したいと思っていた人がいたようですね。タブ区切りは存在してたのに、IANA(Internet Assigned Numbers Authority) MIME(Multipurpose Internet Mail Extensions)*8のCSVの登録も2005年までなかったのですね。そういえば、2000年以降はXMLが流行っていたのを思い出しました。

2. Definition of the CSV Format(CSVフォーマットの定義)

 今回の核となる部分です。

1. 1レコードの区切りに関する規定
1.各レコードは、改行コード(CRLF)で区切られた1つの分離した行である。

 レコードの区切りは、改行コード(CRLF)と定義されています。CRLFは、&x0D &x0A両方の使用が定義されています。(CRLF)がRFC 4180の規定のようです。

2. 1ファイル中の最後のデータの行末に関する規定
2.ファイル最後のレコードの行末には、改行コード(CRLF)はあっても無くても良い。
  aaa,bbb,ccc CRLF
  zzz,yyy,xxx

 てっきりファイルの最後の行にも改行コード(CRLF)をつけるものだと思っていましたが、RFC 4180上は無くても良いのですね。過去、ファイルの最後に改行コードがないファイルを何回も見ましたが、標準通りなのでした。最後の改行コードの有無(特にないケース)は昔プログラムを作った時の盲点だったような気が。。。。もう忘れます。

3. 1ファイル中の1行目のレコードに関する規定
3.ファイルの1行目として、ヘッダー行がオプションとして通常行と同じ書式を持ち、つけられることがある。このヘッダー行にはファイル中の各フィールドのデータ名が記され、ファイルの2行目以降と同数のフィールドを持つべきである[should contain]。(ヘッダー行の有無[the presence or absence of the header line]は、このMIMEタイプのオプション”header”パラメータで示すのが望ましい[should be indicated])。
  field_name,field_name,field_name CRLF
  aaa,bbb,ccc CRLF
  zzz,yyy,xxx CRLF

 1行目にフィールド名が定義されているファイルも、RFC 4180上はCSVファイルなんですね。フィールド名を表すのでフィールド数は以降の行と同じでないといけないようです。

 更に元の仕様でもカッコで括られ、MIMEタイプのオプション "header" パラメータにヘッダーの有無を英語の先生にも聞いたのですが、"should be indicated"和訳が難しいです。直後の例にも出ていないのですが、要は、

 mimeの指定を"text/csv; header=present" とか "text/csv; header=absence" とするのが望ましいようです。 元々、ローカルで使ったりしていただけで。。。

 ひゃーー!!!MIMEのheader オプションを考慮をした実装や設定したことないです。。。。その場限りの仕様を決めていました(懺悔)

 1行目がフィールド名だと、MS-ACCESSなどに新規のテーブルを作成して読込ませるときには、フィールドの型ちょっとだけ便利ですね。フィールドの型をちゃんと指定しないと大変な目にあうことが多かったですけど。

 ということで、さらりと次に行きましょう。

4. 1行の中のデータと半角スペースの扱いに関する規定
4.ヘッダーおよび各レコードは、カンマで区切られた1つ以上のフィールドがある[there may be]。1つのファイル内では各行のフィールドの数は同じである。半角スペース[spaces]はフィールドの一部分として含まれ、無視をしてはいけない。1行のレコードの最後は、カンマで終了してはいけない。
  aaa,bbb,ccc

 カンマの例は記載していますが、半角スペースについて例がありません。著者さんはどうされたのでしょうか。半角スペースはspacesと複数形だったので[ ]で原文を補足しました。今までの経験では、1つ以上の半角スペースだけのフィールドや、フィールド内先頭や末尾の半角スペースは単数、複数個に限らず無視される実装がありました。nullとして扱われることもありました。無視をしないのが、RFC 4180の仕様のようです。

 また、カンマで終了してもいけないと、RFC 4180では規定していますね。

5. 各フィールドのデータの記述方法に関する規定
5.各フィールドはダブルクォーテーションで囲んでも良いし、囲まなくても良い。(とはいえ、Microsoft Excelのようないくつかのプログラムは全くダブルクォーテーションを全く使わない[not use ..... at all]。)もし、ダブルクォーテーションでフィールドが囲まれていなければ、そのフィールド内には、ダブルクォーテーションが含めることができない[may not]。
  "aaa","bbb","ccc" CRLF
  zzz,yyy,xxx

 ダブルクォーテーションでデータを囲む仕様です。MacのEXCELでも1990年代から条件によっては、ダブルクォーテーションで囲まれるので対応したプログラムを作っていたのですが、Y. Shafranovichさんの周りでは違っていたのか、私の誤訳?? 判らないです。後続の文章 ”may not” は、「することができない」ですね。よく勘違いします。フィールドのデータ中にダブルクォーテーションを入れるにはダブルクォーテーションで囲む必要があります。

6. ダブルクォーテーションで囲む必要のあるフィールドデータに関する規定
6.改行(CRLF)、ダブルクォーテーション、コンマを含むフィールドは、ダブルクォーテーションで囲むべきである。
  "aaa","b CRLF
  bb","ccc" CRLF
  zzz,yyy,xxx

 一行目 "b CRLF"と 二行目 bb" までが、一つのフィールド内のデータです。EXCLEの一つのセル内で改行を多用すると、複数行のデータが一つのセルに取り込まれますね。RFC 4180の仕様では、一つのフィールド内の改行コードもCRLFで定義されています。 

7. データを囲むダブルクォーテーションと、データ内のダブルクォーテーションに関する規定
7.ダブルクォーテーションでフィールドが囲まれている場合、フィールド内に存在するダブルクォーテーションは、別のダブルクォーテーションで先にエスケープしなければならない。例として、
  "aaa","b""bb","ccc"

 二番目のフィールドの中身は、b"bb ですね。①データを囲む先頭のダブルクォーテーションか、②データ中のエスケープ用のダブルクォーテーションか、③データのダブルクォーテーションか、④データを囲む末尾のダブルクォーテーションか、1文字ずつ読みこんでプログラムは判断しないといけません。今は、オープンソースを使う方法もありますが、30年前はCで頑張って自分で実装していたのを思い出します。

 この章の最後は、ABNF記法についてですが、省略します。  

3. MIME Type Registration of text/csv (MIMEタイプ)

 MIME申請に関する内容なので、気になったところだけを抜粋します。

必須パラメータ
必須パラメータ なし

なしですね。

オプションパラメータ
オプションパラメータ: charset,  header
  • 通常CSVは、US-ACSIIであるが、IANAの"text"ツリーで定める別の文字セットも"charset"パラメータをつけて使用してもよい。
  • "header"パラメータは、ヘッダー行の有無を示す。有効な値は"present"(ヘッダー行あり)または"absent"(ヘッダー行なし)である。このパラメータを使用しないと選択した実装では、ヘッダー行の有無を自分で決めなければならない。

header ありかなしかのどちらかでしかないのですが、オプションでした。自分で決めなさいとの事。仕方ないですね。

エンコード考慮事項
RFC 2046の4.1.1 で規定したように、このメディアタイプは、改行に CRLF を用いる。とはいえ、実装者は別の値が用いられることも気をつけるべきである。

「改行はCRLFと規定していましたが、別の場合もあるから気をつけてね。」と書かれています。以前は、MS-DOS⇒CR LF、UNIX⇒LF、Macintosh⇒CR と改行コードが異なっていて、プログラムかいた時も気をつけていたことを思い出しました。

セキュリティ考慮事項

「悪意を持ったバイナリデータを入れられることや個人情報に気をつけてね。」とありますが、ここでは省略致します。

相互運用性の考慮事項
1つの決まった仕様が無かった為、実装間でかなりの差異がある。実装者は、CSVファイルを処理する時は、「自分のすることは保守的に、他所から受け取るものは寛容な態度になる(RFC 793)」べきである。 共通となる定義は、2章で見出せる。
オプションパラメータ"header"を使用しないと決めた実装では、ヘッダー行の有無を自分で決めなければならない。

まぁ仕方ないとして、相手のCSVファイルを受取るのですね。RFC 793では、2.10. Robustness Principle(堅牢性の原則)の項で、 TCPの実装で記述しています。

"header"パラメータについて、「重要なのでもう一回書きます!!!」って感じでしょうか。

既出の仕様

 非公式の仕様がいっぱいあるが、「正」となる仕様がない。と記述していますが、省略します。

4節以降

4節以降は以下ですが、データの中身とは異なるので割愛します。

4. IANA Considerations (IANA考慮事項)

5. Security Considerations (セキュリティ考慮事項)

 この5節では、3節で記載されたセキュリティ考慮事項がほぼ再掲されています。

6. Acknowledgments (謝辞)

7. References (参考文献) 

CSVの実際(クイズあり)

EXCELからのCSV出力

  さて、次の画面をCSVにするとどうなるでしょう。(30年前にテストしてみたMacintoshのEXCELからCSVを出力したことを今のWindow10上のEXCEL2016で実験してみました。以下のEXCELのB列はどのようにCSV出力されるでしょうか?C列は次のデータと判るようにデータを追加しています。

f:id:money_order:20210315162312p:plain

  結果が判るように、エディターで表示したのがこちらです。着目データ以外をハッチングしています。

f:id:money_order:20210315165400p:plain

 Case1) Case1(1行目)では、EXCELセル上一つが、CSVファイル中では、①フィールド開始の、②エスケープ用の、③実際のデータの、④フィールド終了の の4つに替わっています。RFC-4180通りですね。

 Case3) Case3(3行目)、EXCELのセルには '12345 が入っていますが、CSVにはEXCELに対するエスケープ文字が外れて、12345だけが出力されています。

 Case6) Case6(6-8行目)をご覧ください。6-8行目の改行付きコードですが、よく見るとセル内の改行コードはLFのみで、レコードの終わりを示すCRLFと異なっています。1990年代初めにEXCELデータからCSVを出力した際と同じでした!!!!ちなみに、EXCELとほぼ互換の無料ソフトLibre Office 7.0の表計算ソフトでも、低価格でEXCEL互換性を売りにしている Polaris Officeの表計算ソフトでも、EXCEL2016と同じLFのみの出力結果でした。しっかりとダブルクオーテーションで囲まれてはいますね。

 Case7) Case7 の先頭と最後の半角スペースはそのまま出力され、ダブルクォーテーションで括られることもありませんでした。

 CSVをダブルクリックして、EXCELに自動読込することがありますが、その際に、LFのみの改行箇所をCRLFに変えてから実行しても1つのセル内に読込まれ問題はありませんでした。過去からの仕様を合わせているのでしょうか。 

CSV読込プログラムの思い出

 以前は自分で実装しなければいけなかったのですが、現在ではオープンソースのCSV用入力、出力ライブラリーが使用できます。とはいえ、セキュリティの関係で特に金融機関さんでは社外へのインターネットアクセスは不可で、自作せざるを得ないことが多かったと思います。マネックス証券にお世話になる前、いくつかの金融会社様のシステム開発で常駐して、他社の作成したCSVファイル読込プログラムを見ることがありました。その結果、その場での取り決めで、RFC4180とは異なるものも何回か見受けました。「自分のすることは保守的に、他所から受け取るものは寛容な態度になる(RFC 793)」べきでした。

  気付いたら、長くなってしまいました。今回はここまでとしたいと思います。1)EXCEL、ACCESSに読込ませてCSVを授受した時の工夫や、2)SJIS、UTF-8の文字コード対応の工夫など、書ききれませんでした。今後の様子を見て書きたいと思います。

 次回はJSONの仕様 RFC 8259 から抜粋してブログを書きたいと思います。では、また。

小田切 貴秀システム開発推進部 GXグループ エンジニア

f:id:money_order:20210319103913p:plain

*1:JSONは”JavaScript Object Notation”の略です。

*2:そんなの私だけ???

*3:CSVは”Comma Separated Value(s)”の略です。

*4:英語版WikiPediaの受け売りです。すみません。※ Comma-separated values - Wikipedia 

*5:LightSpeed Cというソフトで作り、GUIの作り方などMacの関数の対応が難しかったのを思い出しました。

*6:そりゃそうだ。ちゃんとしたものが2005年までなかったらしい。

*7:2021年3月現在、該当の会社をググったのですが、掲載のWebサイトURLは売りに出されていました。時代を感じます。

*8:MIMEの正式名これって知っていました?ずっと知りませんでした。IANAも知りませんでした。