スクリーンショット_2018-10-22_9

JavaScriptをはじめよう #4 npmを使ってみよう

JavaScriptをはじめる入門記事の連載4回目はnpm(Node.jsのパッケージマネージャー)を使って、CSVを処理するプログラムをいくつか書いてみましょう。

CSV(comma separated values)はカンマ区切りのテキストデータです。

まずはCSVを扱うときにとても便利なVSCodeエクステンションである Rainbow CSV を紹介します。

これをインストールしておくと、VSCodeでCSVファイルを開いた時にとても見やすくなります。

VSCodeはエクステンションでこういった機能追加ができてとても便利ですね。

CSVファイルを作る

新規ファイル作成で、numbers.csv というファイルを作成しましょう。

1,2,3,4,5
6,7,8,9,10

カンマ区切りで1〜5と6〜10を入力します。

さきほど入れた Rainbow CSV のおかげでとてもカラフルです。今回のような場合はあまり意味が無いですが…。

npmを使わないパターン

今回は、CSVファイルの行ごとに足し算をしてそれぞれの結果を出すというやり方にします。先ほどの numbers.csv なら、1行目は15で2行目は40になります。

ファイルを読み込むためにはNode.jsに組み込まれたファイルシステム APIを使う必要があります。

csv-sum-without-npm.js というファイルを作ってみましょう。

const fs = require('fs')
const csvText = fs.readFileSync('numbers.csv', { encoding: 'utf-8'})
console.log(csvText)

require はNode.jsのAPIやインストールされているパッケージや、別のJavaScriptファイルなどを読み込む関数(命令)です。

fs にはいくつもの関数があります。詳しくはドキュメントを読むのが確実です。ただしNode.js APIのドキュメントには英語版しかなく、日本語翻訳はあったとしても10年近く経つような古すぎるものしかありません。

それはさておき2行目の fs.readFileSync はファイルを読み込む関数です。1番目の引数はファイル名で、2番目の引数はオプションです。

もともと fs.readFileSync は文字列を返す関数ではなくて、データを生の形で持つために、Buffer という型で返ってきます。

これはファイルには、画像ファイルやZipファイルのように、テキストとして扱おうとすると壊れてしまうものがあるためです。

{ encoding: 'utf-8' } というオプションによって、このファイルはutf-8の文字列だというのを教えてあげることで、文字列が返ってきます。

csv-sum-without-npm.jsに残りの処理を追加しましょう。

for (const line of csvText.split('\n')) {
  let sum = 0
  for (const number of line.split(',')) {
    sum += Number.parseInt(number)
  }
  console.log(sum)
}

前回やったのと同じようなやり方です。ちょっと違うのは csvText 全体を '\n' という記号で区切っていることです。この記号は改行コード(EnterとかReturnとか押したときに入るやつ)を指します。これで行ごとの文字列にしています。

このコードを実行すると、場合によってはですが、

15
40
NaN

という結果になることがあります。ちなみに NaN は Not a Number の略で数値計算しようとしたけど数値じゃなくなったという時に出てくる数字(?)です。

これはnumbers.csvの最後に空の行があるようなケースです。

for (const line of csvText.trim().split('\n')) {
  let sum = 0
  for (const number of line.split(',')) {
    sum += Number.parseInt(number)
  }
  console.log(sum)
}

文字列に使えるメソッド(関数)として、trim というものがあります。文字列の先頭と最後にスペースや改行などがある場合削るという便利なものです。

この通り、無事NaNも出なくなりました。

ちなみにCSVファイルはテキストがからむとめちゃくちゃ面倒なので、パッケージを使いましょう。

パッケージを使う

そこでnpmです。npmはNode Package Managerの略で、Node.jsのパッケージを管理するツールおよび、そのツールで作られたパッケージを指します。

ただし、パッケージを使うための準備が必要です。

ターミナルのPowerShell で npm init -y を実行すると、package.json というファイルを作ってくれます。このファイルはパッケージ利用で使います。

npm init -y

CSVを処理するパッケージにはどのようなものがあるでしょうか。検索エンジンで、探したいものに npm を付けると探しやすいです。

今回は csv-parse を使ってみましょう。

npm i はパッケージをインストールするコマンドです。 -Spackage.json に情報をセーブするというオプションです。

npm i csv-parse -S

csv-parseには色々な使い方がありますが、一番楽な使い方は同期APIです。じつは同期APIというのはさきほどの fs.readFileSync もそうでした。

同期APIは、ファイルの読み込みやCSVの解読など、処理が終わるまで待つというものです。処理が終わるのを待たない非同期APIもありますが、そちらは連載の後ほどで紹介します。

const parse = require('csv-parse/lib/sync')
const dataMatrix = parse(csvText)
console.log(dataMatrix)

使い方はこのように、csv-parse/lib/sync を読み込んで得た関数 parse に引数としてCSV文字列を渡すだけです。

さきほどの csvText をCSVファイルとして解読すると行列(二次元配列)になって返ってきます。

ここまでのコードでは文字列をカンマや改行コードで区切る処理が必要でしたが、すでに配列になっているためそれらは不要です。

for (const line of dataMatrix) {
  let sum = 0
  for (const number of line) {
    sum += Number.parseInt(number)
  }
  console.log(sum)
}

大分すっきりしていることがわかります。

コツ

前回と今回で色々とデータを処理してみました。文字列、数値、配列。途中結果がわからないと不便ではないでしょうか?

伝統的なやり方として、気になる箇所に console.log を仕込むというプリントデバッグというものがあります。

最後のソースでいえば、8行目の console.log(dataMatrix) がそれにあたります。計算結果を表示するためには不要ですが、 dataMatrix 変数がどういう風になっているか表示しています。

色々なところに console.log を仕込んでみましょう。

ただし、VSCodeには便利なデバッガという機能があります。その説明には少し分量が必要なため、次回解説いたします。

まとめ

・ ファイル読み込みはNode.jsのファイルシステムAPIのファイル読み込み関数の同期版 fs.readFileSync を使う
・ CSVはカンマ区切り文字列なので、もっとも単純なやつなら文字の区切りを split するだけで処理できる
・ ただし、CSVは仕様がわりと複雑なので、特にExcelで作ったものとかは真面目に実装するのは面倒なので、パッケージを使う
・ パッケージは npm init -y で、そのフォルダーのパッケージ情報を初期化してから使う
csv-parse をインストールするコマンドは npm i csv-parse -S
・ 値の確認には console.log を使うと便利

いかがでしたでしょうか?

次回は、デバッガの使い方と、もう少し高度なCSV処理を解説する予定です。

この記事が気に入ったらサポートをしてみませんか?