<前置き>

CSVっていうのは、テキストデータをカンマで区切って二次元に並べたデータを言う。(Wikipedia
見た事あるでしょう。

知ってるだろうけどCSVはゴミ。普及の度合いで言えばマエケンのアナルくらい広がっていて、それ故に世界中のプログラマーが苦しめられている。はず。(被害妄想)
CSVは使いづらい。

かと言ってCSVファイルをxmlだのjsonだので表現しようとするとデータサイズが大きくなる。
なんでかっていうと、xmlもjsonも項目名を1レコードずつねっとりと書きやがるから。あと無用に階層構造になっちゃうし、イジケちゃう.exe

「じゃあどんな記法なら大満足なのか」ということを考えてみる。そういう思考実験の記事である。これは。
むしろ学術論文と言って頂いて差し支えないある。

▼追記:2019/2/26

新しく考え直したやつ。

【再考】テキストデータフォーマット考える

▲追記以上

<はじめに>

CSVへの愛と怒りをこの記事にぶつけることを、ここに宣誓します。

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
      NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and
      "OPTIONAL" in this document are to be interpreted as described in
      RFC 2119.(使うとは言っていない)

<ほんへ>

0.命名

じゃあとりあえずccsvで(超適当)

Ⅰ.わかちかた

現状のCSVはカンマでデータを区切っている。

, ⇙コレ

結果、こうなる↓

姓,名,雌雄,生年月日,風貌,身長,種族,神性
唐澤,貴洋,♂,1978-01-04,イケメン,278.3,有能弁護士,荒魂

レコードは改行文字で分けられている。

見た目からして頼りない。「本当にこの豆粒風情がデータを分けられているのか?」と疑問に思ってしまう貧弱さだ。だからこれはやめたほうがいい。

ちなみに、他にも問題点はある。

  • データにカンマが入っていた場合
    株式会社とかを表現するときに「Co., Ltd.」という文字が企業名のケツについたりする。そんなんがCSVに混ざるとこわれる
  • データに改行文字が入る場合
    CSVは改行文字でもってデータのレコードを分けている。だから、データに改行文字が入っていたらデータこわれる。
  • 小数点をカンマで表現する国がある
    こ↑こ↓を確認してくれ。国によって全く違うのが分かるだろう。
    そういう国はカンマの代わりにピリオドをデリミタに使ったりしているらしい。一貫性こわれる。

対処方法としては、データをダブルコーテーション「”」で囲むという仕様が定められている。が、そのダブルコーテーションをエスケープする仕様が定まってない。定まってるんだけど、それに逆らって円記号(バックスラッシュ)でエスケープしてる輩もいる。あぁん?なんで?

だから、データを山括弧「<>」で囲んだらいいんじゃないだろうか。
さすれば、エスケープをするべき文字列は「<」と「>」と「&」でよかろうもん。
xmlとかhtmlでいう「 &lt;」「&gt;」「&amp;」になる。

バックスペースのエスケープは・・・いらんだろ。(適当)

結果、こうなる↓

<姓>,<名>,<雌雄>,<生年月日>,<風貌>,<身長>,<種族>,<神性>
<唐澤>,<貴洋>,<♂>,<1978-01-04>,<イケメン>,<278.3>,<有能
弁護士>,<荒魂>

みやすぅい(小並感
データ内に改行があることも分かりやすい。
改行文字をエスケープする必要もありませんぜ。

どうせビューア使うんだから見易くする必要性はあんま無いけどな。
でもでも、機械的にも扱いやすいと思う。レコード数取得するスクリプトなんざ簡単に書けるっしょ?
カラムのインデントを揃えても容易に解析できる。

しかしこう見るとカンマの必要性が無いように思えるな。
でもどうせクーロン・オブ・キジョーだからこれでいいや。みやすいし。Foo~↑

追記:カンマいるわ。カンマが無いと、レコード間の改行文字を省略した時に困る。
つまり、レコード送り「><」とカラム送り「><」の見分けがつかなくなる。「>[\r][\n]<」でもってレコード送りを判断してもいいが、パーサー作るのが無駄に面倒になるでしょ。あと\r\nが改行コードとも限らん。俺には開発者を虐待する趣味は無い。かわいいオートマトンで処理できるようにしたい。
ついでに言うとレコード送りを「>,<」にしたほうが文字数は少なくなるなぁと思った。けど、このあと出てくるnullの話により、カラム送りを「>,<」としたい。

Ⅱ.型

ExcelにCSVぶち込んで発狂するのは誰しも通った道だろう。
発狂の原因は、Excelのセルの型「G/標準」が鬼畜の所業をしてくれるからである。

CSVに記載されていた「01」は、いつしか「1」になり、「2017-08-10」は「2017/8/10」に変換され、「1145141919810」は「1.15E+12」と化す。民の笑顔は失われ、神は死に、そして世界は闇に飲まれた。

つまり、「自動でデータを整形してくれる」わけである。「自動で壊してくれる」とも言う。
データを全て文字列として読み込めば壊れないけど、その一連の動作は耳から喀血するほど面倒。

ファイルフォーマットで「列の型」を明示すれば、CCSVをぶち込まれる側も安心だし、出力する時も安心である。ウィンウィンである。

★型の種類

どうすべ。まぁ適当に、歌いながら行こう。誰も実装しないし。

符号 型名 所感
string 文字列 うん
number 数値 そうそう
boolean 論理 いいね
date 日付 おっそうだな
datetime 日時 うん。まぁそうか。
decimal 10進数値 数値でよくね?
null なる ファッ!?
type ファファッ!?
year いらなくね?
month いや、だからいらなくね?
code コード おっしゃってる意味が解らん

なんだこれは。たまげたなぁ。

「日付」以下を見ていこう。

  • 日付
    「yyyy-mm-dd」でよかろう。
    日付も国によって表現方法が違うんだけどね。
    だけど、こっちにはISO 8601ちゃんがバックについてんだよ!ってか年を下二桁で表すってどう考えてもおかしいだろ!百年ごとに改修してんのか!?

    和暦?きょうび流行んねーんだよ。ボケが。エンドで計算して西暦表示にするべし。欲しいのなら文字列で持ってください。

    あと、「8月32日」とかを「9月1日」とかに解釈することを金輪際未来永劫に向けて禁止する。javascript、てめェーだよ てめェー
    データの妥当性チェックができなくなるだろうが。

  • 日時
    これもISO準拠ですね。
    「YYYY-MM-DDThh:mm:ss」でよかろう。
    Tの代わりに半角スペースを入れるっていう説もある。けど却下だ。
    プラスでロケールを考えたいんならそれもISO準拠で。

    「期間」は要らんだろ。項目を二つ作れ。一つにまとめようとすんな。
    週も曜日もいらん。ライブラリに計算させろ。どうしても欲しいなら文字列で持たせるなりしろ。

  • 10進整数(Decimal)
    こんな記事をここまで読んでくれているガチなホモなら分かると思うが、小数値をパソコンに扱わせると誤差が発生する
    だから、decimalだってことを明示できるようにした方がいいと思うんです(小声)
    おまけぐらいに考えておいてくれませんか。

    小数点値はピリオドあるいはカンマ。国によって違うからな。
    桁の大きい数値については三桁ごとに半角空白を挿入してもよい(MAY)。ただし、ピリオドやカンマなど、半角空白以外の文字を三桁の区切りに使用してはならない(MUST NOT)。らしいですよ?(他人事)
    つまり「3643648.93」は「3 643 648.93」か「3 643 648,93」で示される。

  • null
    そもそもnullっていうものが存在してもいいのかっていう話なんだけど、広まっているんだからしょうがない。
    例えば空の文字列は「<>」になるんだけど・・・

    ひらめいた 通報した(幻聴)

    山括弧「<>」で項目を囲むって話をしたんだけど、山括弧がない項目についてはnullってことにすればいいんじゃないか?
    でもパーサーが複雑化するような。まぁいいか(適当)
    文字列以外についても、nullを表現したいときは山括弧なしのほうが良いな。統一するに越したことはない。

    あ、駄目だわ。次レコードへの移動を示す「><」が作れなくなる。
    えーと、nullは「>」で示すようにする。空文字は「<>」。行端でnullデータがあったときは

    <test1-1>,<test1-2>,><test2-1>,<test2-2>,<test2-3>

    って感じになるな。

    データ整形をするときは、今まで通り「><」の間に改行をいれて差し上げろ。


  • 「CCSV」で使用できる型を格納する。
    例えば「文字列型」という情報を格納したりする。
    いわば「型型」という「型」。ヴォエッ!
  • 年、月、コード
    「年」は「yyyy」で「月」は「mm」or「m」。
    「コード」っていうのは、例えば「商品コード」とか「店舗コード」とか「通貨コード」とか、そういうコードの事を言っている。例えば「00110」とか。

    ぶっちゃけた話、こんな型は要らない。
    「年月」は数値、「コード」は文字列でいい。
    だが、これがあれば無用な食い違いを避けることができる。
    詳しくは語らんが、CSVが使われる用途を考えるに、あって損はない。

    「日」を示したいのなら「日付」を使え。「日」だけを単体で扱うのは多分データ構造がおかしい。

    ???「Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away」

    ぼく「完璧なんて目指してないから大丈夫だって安心しろよ~

  • 数式
    んー。気持ちはわかる。
    しかし、この規格については純粋にしておいたほうが良いと思う。データ格納を目的としておきたい。
    例えばこのデータをもとに何らかの操作をしたい時は、メタデータとかの拡張規格としてそれを定義する方がいいだろう。
    数式を定義するにしても、Excelみたいにレコードごとに書くのはアホでしょ?だからメタデータに書かせたいな。

Ⅲ.メタデータヘッダー

メタデータを入れる。

★標準メタデータ

何を入れたいか。あと、書き方。

  • 文字コード
    xmlと同じ。「encoding=”UTF-8″」みたいな。
  • データ生成日時
    これが欲しかったんだろう?
  • データの名前
    例えば「販売データ_0010_yyyymmdd」みたいな、データの名前。大抵の場合ファイル名と一致すると思う。
  • データ種別
    上の例で言うと、この「データ種別」項目は「販売データ」になる。つまり「テーブル名」とか「オブジェクト名」みたいなものやね。
  • 列名
    CSVは、一番上の行が列名になっている。それはメタデータなんで、実データには混ぜない。いいね?
  • 列の型
    さっきの型の話。列に型を指定する。指定しないのもまぁいいだろう。うまあじが損なわれるけどな。
  • ID項目、主キー項目
    ここまでやらせるのは流石におかしいかなぁ。データベースめいてきた。でも、ツールが自動でアラート投げてくれたら嬉し聡ずかしくないか?工数減るぜ?
    あと、CCSVデータの入出力を考える時に「主キーの考察漏れ」が無くなる。事故が減る。
  • 数式
    データの本質に関わる部分ではないから、やはりここでも省略される。
    「ソートルール」とか「セルの色」とか「条件付き書式」とか「数式」とか「元データ内容の修正情報」とか「セルへのコメント」とか「ジャンプのための目印、名前」とか「表示非表示フィルタ」をまとめて表現できるデータファイルを定義しなきゃいけないだろうな。元データはいぢらずに、それをレポートにするファイルが必要だ。

これらのメタデータは別にMUSTにすることもないだろう。いままでのCSVっぽく、シンプルに使えるほうが良い。

でも基本的にツール使って触って欲しいな。
手でいじくると事故るよ。

★メタデータの書き方

xmlでいいかな。いいよね。

適当に考えよう。

>&&CCSV>>
    >&&META as CCSV.meta>>
        >encoding&UTF-8>
        >creationDateTime&YYYY-MM-DDThh:mm:ss>
        >name&販売データ_0010_yyyymmdd>
        >dataType&販売データ>
        >columns&&&LIST type CCSV.ccsvColumn>>
            >num&1>name&囚人番号>type&TYPE&code>isId&true>isKey&true<
            >num&2>name&姓>type&TYPE&string<
            >num&3>name&名>type&TYPE&string<
            >num&4>name&雌雄>type&TYPE&boolean<
            >num&5>name&生年月日>type&TYPE&date<
            >num&6>name&風貌>type&TYPE&string<
            >num&7>name&身長>type&TYPE&number<
            >num&8>name&種族>type&TYPE&string<
            >num&9>name&神性>type&TYPE&string<
        &<
    <
    >&&&CCSV>>
<43044>,<唐澤>,<貴洋>,<♂>,<1978-01-04>,<イケメン>,<278.3>,<有能
弁護士>,<荒魂>
<002760>,<唐澤>,<厚子>,<♀>,<1979-01-04>,<ふつう>,<180,3>,<ダチョウ>,<和魂>
    &<
<

適当になった(有言実行)。何だこのデータ記法っ。全然xmlじゃないし。

・xmlを圧縮したかった。
・エスケープ文字を「<」「>」「&」に絞りたかった。
・冗長性を減らしたかった。

⇒妙なデータになった。やはりヤバい(分析)

「&」の左辺がプロパティ名で、右辺が値。

>&&CCSV>>」の「>&&META>>」は「CCSV」の「META」が始まるって言うことを表現している。「<」で終わり。
つまり「>&&」で始まったら「<」が来るまで、並列な一連の「プロパティ」を記述することができる。
「as」句で型を明示できるから「>&&sampleClass as CLASS>>」みたいにクラスの定義を書くこともできるだろう。

>&&&」で始まったら「&<」が来るまで独自のデータ型になる。例にあるのは「>columns&&&LIST>>」と「>&&&CCSV>>」だな。
「LIST」は「type」句で要素の型を指定している。
「columns」はプロパティ名。

「type&TYPE&string」っていうのは・・・苦肉の策。
「type」っていう名前のプロパティに「TYPE&string」を入れている。全然美しくないな。でも「.」とかスペース使うとエスケープせにゃならんし。
「>&&[hoge] as」と「&&&LIST type」の後の「TYPE」は省略可能。

この記法でクラスを記述しようとしたときに、おそらく「プロパティ名&型」というような記述が必要になるだろう。
「strList」という名前のプロパティの型が「string型のLIST」であった場合、それを表現するときは「strList&TYPE&&&LIST type string」になる。
ユーザー定義型の場合も「prop&TYPE&&&sampleClass」みたいな書き方になるだろう。

冗長性のなさは良いと思う。が、初見で理解しようがないな。
見直して思ったこととして、これはつまりXMLの機能を絞って単純化し、「リスト」とか「スプレッドデータ」を格納できるようにしたものだな。だいぶすっきりした。

いや、もうちょっと考えればもっとスマートにできるような気もするけど。

自分勝手(selfish)にxmlを改変したものだから、「sexml」って名前にしよう。
いや、んー。「三番目のデータ記法」になることを目指して(目指さない)「Third Data Notation」で「TDN」でもいいな。
いや、やっぱ軽いデータを考えるために作ったものだから「lightweight data Notation」で「ldn」って名前にしよう(危険回避)
読み方は・・・「多田野数人」(意味不明)

「CCSV」のビューワーは、「&&&CCSV」と同階層の「&&META」を探して適用する。
ユーザーがメタデータを定義するときはトップレベルに「&&META」を新たに作って、そこに適当に書く。

ぬわ疲。計5時間くらい考えた希ガス。なんて無駄な時間を。

Ⅳ.略記

メタ無しで書く。が、型は指定したい人へ。

<囚人番号><code>,<姓><string>,<名><string>,<雌雄><boolean>,<生年月日><date>,<風貌><string>,<身長><number>,<種族><string>,<神性><string>
<43044>,<唐澤>,<貴洋>,<♂>,<1978-01-04>,<イケメン>,<278.3>,<有能 弁護士>,<荒魂> <002760>,<唐澤>,<厚子>,<♀>,<1979-01-04>,<ふつう>,<180,3>,<ダチョウ>,<和魂>

わりと妥当な形になったな。
先頭行が自動で列名行として読まれる。

Ⅴ.まだ特に考えてない

あと必要なのは連想配列とか?

ここ見た感じだと、なんか大丈夫そうだな。スタック、キュー、セットはLISTに別名つけてやるだけで良いだろ。
「連想配列」は「連想配列要素」、「連結リスト」は「連結リスト要素」があればいい。別名も必要だと思うが。

あとは~「参照」型と、スクリプトかなぁ(嘔吐)

<結論>

チカレタ…(小声)
なんか考えついたら追記するわ。

んで気が向いたらIETFにぶんなげる。