CSVデータをインポートする実装で、FileAPI周りでBlobとかArrayBufferとかよく見かける、名前だけ知ってるもの達を整理してみた。
CSVとは
そもそもCSVファイルとは、Comma Separated Values
の略で、各項目がカンマ(,)で区切られたテキストデータのことです。データの容量が軽く、読み書きや編集が容易であるという特徴があります。
CSVファイルとExcelファイルの最も大きな違いは「互換性が高いか、装飾・機能の自由度が高いか」ということです。
拡張子「.csv」のCSVファイルは互換性が高く、Excelのみならずメモ帳、メールソフト、データベースソフトなどほとんどのソフトに取り込んで閲覧、編集することが可能です。そのため、Excelファイルを扱えるかが不明な相手とデータのやり取りを行う際はCSVに変換される場合が多いです。
データのじかん から引用
FIle API
FIle API は、ウェブアプリケーションがローカルマシンにあるファイルへアクセスしてJavaScriptで操作できるようにするためのAPIです。
その中の1つであるFileReaderを使って、アップロード、インポートなどが行われる
FileReader API
その名の通り、Fileオブジェクトを実際に読み込む
読み込みメソッド
readAsArrayBuffer
: ファイルをArrayBufferとして読み込む
readAsText
: ファイルをテキストとして読み込む
readAsDataURL
: ファイルをDataURLとして読み込む
readAsBinaryString
: ファイルをバイナリ形式で読み込む
サンプル
CSVをインポートする流れを以下のライブラリを用いて実装するサンプルです。
使用ライブラリ
ExcelJS
: JSでExcelファイルを扱うようにできるライブラリ
Stream-Browserify
: NodeのストリームAPIをブラウザで動かすライブラリ
ExcelJSのCSV読み込みの仕様
stream
で渡さないといけない (以下ドキュメントより引用)
// read from a stream
const workbook = new Excel.Workbook();
const worksheet = await workbook.csv.read(stream);
以下CSVファイルをインポートして、streamに変換し、ExcelJSに渡すまでのサンプルです。
// JSでExcelファイルを扱うようにできるライブラリ
import ExcelJS from 'exceljs'
// NodeのストリームAPIをブラウザで動かすライブラリ
import { Readable } from 'stream-browserify'
import { Buffer } from 'buffer'
// グローバルスコープで利用できるのでインポートしなくても利用できる
const reader = new FileReader();
// リーダーにファイルをArrayBufferとして読み込む
reader.readAsArrayBuffer(file);
// 読み込みが成功して完了したら、以下のonloadメソッド内で読み込み結果が見れる
// この場合はArrayBufferデータ
reader.onload = () => {
// リーダーがArrayBufferで読み込んだデータ
const contents = reader.result
// ExcelJSのインスタンスを作成
const workbook = new ExcelJS.Workbook()
// ArrayBufferをBufferObjectに変換
const buffer = Buffer.from(contents)
// ExcelJSがストリームからデータを読み取れるようにする
const stream = new Readable()
stream.push(buffer)
// ストリームの終了
stream.push(null)
// ExcelJSのCSVリーダーにストリームを渡す
await workbook.csv.read(stream)
return workbook.worksheets
}
処理フローをまとめると
・ユーザーがFileを選択
・FileをArrayBufferとして読み込む
・読み込みが完了したら、resultプロパティにArrayBufferが格納される
・ArrayBufferをBufferに変換する
・BufferをReadable Streamに変換する
・Readable StreamをExcelJSのCSVリーダーメソッドに渡すと、JSで扱えるデータにしてくれる
JavaScriptで扱えるバイナリデータ
ArrayBuffer, Uint8Array, DataView, Blob, File, etc.
基本となるバイナリオブジェクトは ArrayBuffer です。これは固定長の連続したメモリ領域への参照です。
バイナリデータとは
0と1の2進数で表現されるデータのことを指します。コンピューターはこの形式のデータを扱うことが得意であり、多くのデータがバイナリーデータとして保存されます。例えば、画像、音声、動画、プログラムなどがバイナリーデータの形式で保存されています。
1. ArrayBuffer
JavaScript でバイナリデータを扱うときには ArrayBuffer を使うのが便利です。 ArrayBuffer は固定長のバイナリデータバッファを表します。
File API の FileReader などはデータを読み取った結果を ArrayBuffer として返します。そのため 「バイナリデータを使う時は ArrayBuffer を活用する」と覚えておくと、わかりやすいです。
ArrayBuffer は Array とは何の共通点もありませんので、配列データではない。
長さは固定で、増減することはできません。
メモリの中で、長さちょうどのスペースをとります。
個々のバイトにアクセスするには、buffer[index] ではなく、別の “view” オブジェクトが必要です。
2. Blob
BlobはBinary Large Objectの略
一般的なバイナリデータをJavaScriptで扱えるようにしたり、新しく生成することができます。
バイナリデータを簡単に説明すると「0」と「1」で表現される2進数だけでテキストや画像などをデータ化したものになります。また、Blobを拡張してブラウザ上からファイルを読み込んだりダウンロードするFile APIも一緒によく使われます。
JavaScriptのネイティブフォーマットではないデータを表すために使用されます。簡単に言うと、Blobは画像、zipファイル、オーディオファイルなど、さまざまなタイプのデータを扱うために使われます。
3. File
ファイルについての情報を提供したり、ウェブページ内の JavaScript からその内容にアクセスできるようにしたりします。Blobを継承してる
4. Buffer
Node.jsでは、文字列とバイナリデータ(バイト列)はまったく別のものとして扱われる。前者を扱うためのクラスがStringで、後者を扱うNode.js独自のクラスがBuffer。
Node.jsでは文字列とバイト列は厳密に区別されており、文字列の格納にはStringクラスを、バイト列の格納にはBufferクラスを利用するようになっている。
ストリームAPI
データを逐次的に読み込みながら処理したいときに利用するAPI
以下の3つの要素がある
ReadableStream データソースからデータを読み出してストリームとして提供する
TransformStream ストリームから受け取ったデータを変換してストリームとして提供する
WritableStream ストリームから受け取ったデータをデータソースに書き込む