Help us understand the problem. What is going on with this article?

Kinx ライブラリ - CSV Parser

CSV

はじめに

「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。言語はライブラリが命。ということでライブラリの使い方編。

今回は CSV パーサーです。TSV もあります。

使い方

using CSV

CSV ライブラリは標準組み込みではないため、using ディレクティブを使用して明示的に読み込む。

using CSV;

全てを一度にパース

ファイルを読み込んで全体をパースするには、CSV.parse() を使う。

using CSV;
var r = CSV.parse("filename.csv");

データの形式は以下の通り。全ての行オブジェクトの配列として返す。行オブジェクトには data フィールドがあり、そこに配列として各要素の文字列が設定される。ただし、コメント行(先頭が #)の場合、data フィールドは空となり comment フィールドにコメント文字列が入る(# も含む)。

[{
    "data": ["aaa", "bbb", "ccc"]
}, ..., {
    "data": {},
    "comment": "# comment"
}]

1行ずつコールバック

行数が多い場合、全体を一気にパースすると大量にメモリを消費する可能性がある。そこで、以下のように 1 行ずつコールバックさせることもできる。コールバックの引数は 1 行分の行オブジェクトとなる。

using CSV;
CSV.parse("filename.csv", &(row) => {
    System.println(row);  // like `{ data: ["aaa", "bbb", "ccc"] }`
});

尚、この場合 CSV.parse() は値を返さない(null を返す)。

文字列をパース

文字列をパースする場合、CSV.parseString() を使う。コールバック版も同様。

using CSV;
var r = CSV.parseString(csvString);
CSV.parseString(csvString, &(row) => {
    ...
});

CSV 仕様

解釈する CSV の仕様は以下の通り。

  • 先頭文字が # の場合、コメント行と認識。
  • ダブルクォートは無くても良い。
  • ,"、改行を含めたい場合はダブルクォートが必要。
  • ダブルクォート内では以下の仕様。
    • , は直接記載可能。
    • """ と重ねて記載。
    • 改行はそのまま改行することで表現する。
  • 最終行の末尾に改行コードは無くても良い。

サンプル

サンプルとして以下をパース。

# comment in CSV.
abcde,efgh,non-quoted string
"abcde","efgh","quoted string"
"abcde",efgh,"quoted & non-quoted string in the same row"
"abcde",efgh,"can use , or "" in csv"
"abcde",efgh,"can use newlines

in the row"
# another comment in CSV.
abcde,efgh,not necessary \n the end of csv

結果はこうなる。

[{
    "data": {},
    "comment": "# comment in CSV."
}, {
    "data": ["abcde", "efgh", "non-quoted string"]
}, {
    "data": ["abcde", "efgh", "quoted string"]
}, {
    "data": ["abcde", "efgh", "quoted & non-quoted string in the same row"]
}, {
    "data": ["abcde", "efgh", "can use , or \" in csv"]
}, {
    "data": ["abcde", "efgh", "can use newlines\n\nin the row"]
}, {
    "data": {},
    "comment": "# another comment in CSV."
}, {
    "data": ["abcde", "efgh", "not necessary \\n the end of csv"]
}]

TSV

TSV とは CSV のカンマ区切りがタブ区切りになったもの。

using CSV は一緒。使うときに CSVTSV にするだけで使える。

using CSV;
var r = TSV.parse(tsvFilename);
TSV.parseString(tsvString, &(row) => {
    ...
});

パーサー

パーサー自体を Kinx で書いています。

パーサーの形態は1文字先読みの再帰下降パーサーですが、そもそも CSV の仕様に再帰的な要素がないので再帰しません。言うなればただの下降パーサーです。

コードは GitHub にあります。全体で100行ちょっとしかないのですぐ理解できるかと思います。

内部ライブラリ用の特殊キーワードについて

ちなみに、_class_function というキーワードが使われていますが、一般では使いません。意味は classfunction と同様です。

何が違うかというと、_ 付きのほうは例外発生時にスタックトレースに情報を残さないといった動作をします(また、-d オプションで VM コードを表示しません)。これは内部ライブラリの場合、スタックトレースに情報を残すと混乱する可能性があるためです。例えば、例外の起点が内部ライブラリの行番号を示していると、そこに問題があると勘違いする可能性があるためで、例外の起点はあくまでユーザー・コードを示すようにしています。VM コード出力でもユーザー・コードの邪魔になると考えられるので表示しないといった配慮がなされる形です。

このストラテジーに従うと逆にライブラリ内部にバグがあった場合は調査困難になりますが、通常ケースでパラメーター異常による例外、といったケースのほうが一般的と考えられるので、この仕組みを入れてあります。尚、内部ライブラリ自体のデバッグをしたい場合は _classclass に、_functionfunction に変更すればできます。

おわりに

CSV パーサーは何か既存のライブラリを使おうかと思って探したんですが、イマイチ統合するのが手間取りそうだったのと、実は簡単なんじゃないかと思ってスクラッチで書いてみました。何か問題があればお知らせください。

ではまた、次回。

Kray-G
C++ & boost lover だったが、禅の心持ちというかシンプル・イズ・ザ・ベストの精神で C に回帰中。メタルからロックンロールに戻ってきて Rolling Stones に今更夢中。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした