MENU

ファイル操作ArrayBuffer

【Node.js】 ファイルをArrayBuffer経由で読み込み・保存する

更新日:2021/07/06

元々Node.jsには固有のモジュールとしてBufferオブジェクトが存在していて、ファイルから読み込んだデータはBufferオブジェクトに格納されるように設計されています。

 

しかしECMAScriptの2015年版で、バッファーとして動作可能なArrayBufferオブジェクトがJavaScritとして標準搭載されました。

 

そのためブラウザ等でJavaScriptコードを作成してきた人は、BufferよりもArrayBufferの方が使いやすいです。

 

そこで今回は、Node.jsでファイルの入出力する際にArrayBufferを経由する方法をお伝えします。

 

前提

 

ArrayBufferは任意のバイト数のメモリ(バッファー)を確保しが、確保したメモリに直接アクセスすることができません。

 

アクセスするには、DataViewまたはTypedArrayというオブジェクトをインターフェースとして使用します。

 

そのためこの記事では、DataViewやTypedArrayを用いた操作についてお伝えしています。

 

ArrayBufferおよびDataViewとTypedArrayについては、こちらを読んでみてください。
【JavaScript】 ArrayBufferとTypedArray-メモリを確保してアクセス

ファイルからArrayBufferにデータを読み込む

 

ファイルからデータを読み込み、ArrayBufferとして受け取るには、次のようにします。

 


const fs = require("fs");

fs.readFile("./binary.dat", (err, result) => {
    if (err) throw err;

    const u8 = new Uint8Array( result.buffer );
    
        // 同じバッファーを参照しているかの確認
    console.log( u8.buffer === result.buffer );  // true
});

 

コールバック関数の第二引数は、Node.js固有のBufferオブジェクトです。
BufferオブジェクトとArrayBufferオブジェクトは、仕様が異なるオブジェクトです。
そのためDataViewまたはTypedArrayに、バッファーとして渡すことができませんでした。

 

しかしNode.js v8からBufferオブジェクトに追加されたbufferプロパティは、ArrayBufferオブジェクトを返します。
そのため、このプロパティを使用して、DataViewまたはTypedArrayオブジェクトを作成することができます。

 

ネットで検索すると、次のようなコードを紹介している記事がありますが、古い記事が現在も上位表示されているようです。

 

bufferプロパティ導入以前のTypedArray変換

 


const u8 = new Unit8Array( result.length );
for (let i = 0; i < result.length; i++ ) {
        u8[i] = result[i];
}

 

現在はbufferプロパティを使用できるので、ループで一つずつ代入する必要はありません。

ArrayBufferデータをファイルに書き込む

 

ArrayBufferデータをファイルに書き込む場合、基本的にはDataViewまたはTypedArrayオブジェクトをfs.writeFileに渡すだけです。

 

ArrayBufferデータの書き込み例

 


const fs = require("fs");

const arr = Uint8Array.of(100,200,300,400);
fs.writeFile("./binary.dat", arr, err => {
    if (err) throw err;
    console.log("出力しました");
});

 

TypedArrayオブジェクトの種類に係らず、バッファーの内容がそのまま出力されます。

2バイト以上のTypedArrayは注意が必要

2バイト以上のTypedArrayオブジェクトを使用する場合は注意が必要です。

 

TypedArrayへのアクセスは、現在の環境のエンディアンが考慮されます。
そのためエンディアンが異なるシステム間でデータのやり取りがあると、上手く受け渡せない可能性があります。

 

詳しくは次の記事を読んでみてください。
【JavaScript】 2バイト以上のTypedArrayバイナリ保存はエンディアンに注意

スポンサーリンク

記事の内容について

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

OFUSEを設置してみました。
応援いただけると嬉しいです。