Node.js Buffer モジュール
Buffer は Node.js においてバイナリデータストリームを処理するためのクラスです。コンピュータでは、すべてのデータは最終的にバイナリ形式で保存・転送されます。Buffer は、これらの生のバイナリデータを Node.js で効率的に処理する方法を提供します。
Buffer は、生のバイナリデータを格納するための専用の固定サイズの「コンテナ」と考えることができます。JavaScript の通常の配列とは異なり、Buffer は固定サイズのメモリブロックを割り当てるため、大量のバイナリデータを処理する際により効率的です。
なぜ Buffer が必要なのか?
Web 開発では、さまざまなバイナリデータを頻繁に扱う必要があります。例えば:
- ファイルの読み書き操作
- ネットワーク通信におけるデータ転送
- 画像処理
- 暗号化・復号化操作
JavaScript は当初、ブラウザでの DOM 操作を主目的として設計されており、バイナリデータの処理能力は限られていました。Node.js はサーバーサイドランタイムとして、より強力なバイナリデータ処理能力を必要とします。これが Buffer モジュールが存在する理由です。
Buffer の作成
Node.js で Buffer を作成する方法はいくつかあります:
1. Buffer.alloc() を使用する
例
const buf1 = Buffer.alloc(10);
console.log(buf1); // <Buffer 00 00 00 00 00 00 00 00 00 00>
2. Buffer.allocUnsafe() を使用する
例
// 古いデータが含まれる可能性があるため、高速だが安全性は低い
const buf2 = Buffer.allocUnsafe(10);
console.log(buf2); // <Buffer の内容は不定>
3. 配列から作成する
例
const buf3 = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
console.log(buf3); // <Buffer 62 75 66 66 65 72>
4. 文字列から作成する
例
const buf4 = Buffer.from('Hello Node.js');
console.log(buf4); // <Buffer 48 65 6c 6c 6f 20 4e 6f 64 65 2e 6a 73>
Buffer のよく使うメソッド
データの書き込み
例
// 文字列を書き込む
buf.write('Hello');
console.log(buf); // <Buffer 48 65 6c 6c 6f>
// 書き込み時にエンコーディングを指定する
const buf2 = Buffer.alloc(10);
buf2.write('你好', 'utf8');
console.log(buf2); // <Buffer e4 bd a0 e5 a5 bd 00 00 00 00>
データの読み取り
例
// 文字列として読み取る
console.log(buf.toString()); // Hello World
// 一部の内容を読み取る
console.log(buf.toString('utf8', 0, 5)); // Hello
Buffer のコピー
例
const buf2 = Buffer.from('World');
const buf3 = Buffer.alloc(10);
buf1.copy(buf3, 0); // buf1 を buf3 の先頭にコピーする
buf2.copy(buf3, 5); // buf2 を buf3 の5バイト目から始まる位置にコピーする
console.log(buf3.toString()); // HelloWorld
Buffer の連結
例
const buf2 = Buffer.from(' ');
const buf3 = Buffer.from('World');
const result = Buffer.concat([buf1, buf2, buf3]);
console.log(result.toString()); // Hello World
Buffer と文字列
Buffer と文字列は相互に変換できますが、エンコーディングに注意する必要があります。一般的なエンコーディングは次のとおりです:
- 'utf8' (デフォルト)
- 'ascii'
- 'base64'
- 'hex'
例
例
const str = 'Hello Buffer';
const buf = Buffer.from(str);
// Buffer を文字列に変換する
console.log(buf.toString()); // Hello Buffer
// 異なるエンコーディングを使用する
console.log(buf.toString('hex')); // 48656c6c6f20427566666572
console.log(buf.toString('base64')); // SGVsbG8gQnVmZmVy
Buffer の実際の応用
1. ファイル操作
例
// ファイルを読み込んで Buffer にする
fs.readFile('example.txt', (err, data) => {
if (err) throw err;
console.log(data); // <Buffer ...>
console.log(data.toString()); // ファイルの内容
});
// Buffer をファイルに書き込む
const content = Buffer.from('Hello File System');
fs.writeFile('output.txt', content, (err) => {
if (err) throw err;
console.log('文件已保存');
});
2. ネットワーク通信
例
http.createServer((req, res) => {
const chunks = [];
req.on('data', (chunk) => {
chunks.push(chunk); // データチャンクを収集する
});
req.on('end', () => {
const body = Buffer.concat(chunks); // すべてのデータチャンクを結合する
console.log(`受信したデータ: ${body.toString()}`);
res.end('数据已接收');
});
}).listen(3000);
3. 画像処理
例
const sharp = require('sharp');
// 画像を読み込んで Buffer にする
fs.readFile('input.jpg', (err, data) => {
if (err) throw err;
// sharp を使用して Buffer 内の画像データを処理する
sharp(data)
.resize(200, 200)
.toBuffer()
.then(outputBuffer => {
// 処理後の Buffer をファイルに書き込む
fs.writeFile('output.jpg', outputBuffer, err => {
if (err) throw err;
console.log('图片处理完成');
});
});
});
注意事項
メモリ管理:Buffer はメモリを直接操作するため、大きな Buffer を割り当てるとアプリケーションのパフォーマンスに影響します。
安全性:
Buffer.allocUnsafe()機密データが含まれる可能性があるため、使用時には注意が必要です。エンコーディングの一貫性:Buffer と文字列を変換する際は、同じエンコーディングを使用するようにしてください。
バージョンの違い:Node.js の古いバージョン (v5.x 以前) の Buffer API は新しいバージョンとは異なります。最新の API を使用することをお勧めします。
パフォーマンスの考慮:大量のデータ処理において、Buffer を適切に使用するとパフォーマンスが大幅に向上します。
Buffer は Node.js でバイナリデータを処理する中核モジュールです。その動作原理と使い方を理解することは、効率的で信頼性の高い Node.js アプリケーションを開発するために不可欠です。
Bufferモジュールのメソッドとプロパティ一覧
BufferNode.js でバイナリデータを処理するための中核モジュールです。以下は Buffer モジュールの主なメソッドとプロパティです:
Buffer クラスのプロパティ
| プロパティ/メソッド | 説明 | 導入バージョン |
|---|---|---|
| Buffer.poolSize | 事前に割り当てられた内部 Buffer インスタンスのサイズ(バイト)。変更可能 | 0.11.3 |
| Buffer.from() | 文字列、配列、またはバッファから新しい Buffer を作成する | 5.10.0 |
| Buffer.alloc() | 指定サイズの初期化済み Buffer を作成する | 5.10.0 |
| Buffer.allocUnsafe() | 指定サイズの未初期化 Buffer を作成する(高速だが安全ではない) | 5.10.0 |
| Buffer.allocUnsafeSlow() | 未初期化 Buffer を作成する(共有メモリプールを使用しない) | 5.12.0 |
| Buffer.isBuffer() | オブジェクトが Buffer かどうかを検査する | 0.1.101 |
| Buffer.isEncoding() | エンコーディングが有効かどうかを検査する | 0.9.1 |
| Buffer.concat() | Buffer の配列を結合する | 0.7.11 |
| Buffer.byteLength() | 文字列のバイト長を返す | 0.1.90 |
| Buffer.compare() | 2つの Buffer を比較する | 0.11.13 |
Buffer インスタンスのメソッド
| メソッド | 説明 | 導入バージョン |
|---|---|---|
| buf.length | Buffer のバイト長 | 0.1.90 |
| buf.write() | Buffer に文字列を書き込む | 0.1.90 |
| buf.toString() | Buffer を文字列にデコードする | 0.1.90 |
| buf.toJSON() | Buffer の JSON 表現を返す | 0.9.2 |
| buf.equals() | 2つの Buffer が等しいかどうかを比較する | 0.11.13 |
| buf.compare() | Buffer を比較してソート順序を返す | 0.11.13 |
| buf.copy() | Buffer データをコピーする | 0.1.90 |
| buf.slice() | Buffer の部分ビューを作成する | 0.3.0 |
| buf.includes() | Buffer に値が含まれているかどうかを検査する | 5.3.0 |
| buf.indexOf() | 値が最初に出現する位置を返す | 1.5.0 |
| buf.lastIndexOf() | 値が最後に出現する位置を返す | 6.0.0 |
| buf.fill() | 指定した値で Buffer を埋める | 0.5.0 |
| buf.readUIntLE() | 符号なしリトルエンディアン整数を読み取る | 0.5.5 |
| buf.readUIntBE() | 符号なしビッグエンディアン整数を読み取る | 0.5.5 |
| buf.readIntLE() | 符号付きリトルエンディアン整数を読み取る | 0.11.15 |
| buf.readIntBE() | 符号付きビッグエンディアン整数を読み取る | 0.11.15 |
| buf.readDoubleBE() | ビッグエンディアン64ビット倍精度浮動小数点数を読み取る | 0.11.15 |
| buf.readDoubleLE() | リトルエンディアン64ビット倍精度浮動小数点数を読み取る | 0.11.15 |
| buf.readFloatBE() | ビッグエンディアン32ビット浮動小数点数を読み取る | 0.11.15 |
| buf.readFloatLE() | リトルエンディアン32ビット浮動小数点数を読み取る | 0.11.15 |
| buf.writeUIntLE() | 符号なしリトルエンディアン整数を書き込む | 0.5.5 |
| buf.writeUIntBE() | 符号なしビッグエンディアン整数を書き込む | 0.5.5 |
| buf.writeIntLE() | 符号付きリトルエンディアン整数を書き込む | 0.11.15 |
| buf.writeIntBE() | 符号付きビッグエンディアン整数を書き込む | 0.11.15 |
| buf.writeDoubleBE() | ビッグエンディアン64ビット倍精度浮動小数点数を書き込む | 0.11.15 |
| buf.writeDoubleLE() | リトルエンディアン64ビット倍精度浮動小数点数を書き込む | 0.11.15 |
| buf.writeFloatBE() | ビッグエンディアン32ビット浮動小数点数を書き込む | 0.11.15 |
| buf.writeFloatLE() | リトルエンディアン32ビット浮動小数点数を書き込む | 0.11.15 |
| buf.swap16() | 16ビットのバイト順を交換する | 5.10.0 |
| buf.swap32() | 32ビットのバイト順を交換する | 5.10.0 |
| buf.swap64() | 64ビットのバイト順を交換する | 6.3.0 |
| buf.keys() | Bufferキーのイテレータを作成する | 1.1.0 |
| buf.values() | Buffer値のイテレータを作成する | 1.1.0 |
| buf.entries() | [index, byte] イテレータを作成する | 1.1.0 |
エンコーディングの種類
Bufferがサポートするエンコーディングタイプ:
| エンコーディング | 説明 |
|---|---|
| utf8 | マルチバイトUnicode文字 |
| utf16le | 2または4バイトのUnicode文字 |
| latin1 | ISO-8859-1 |
| ascii | 7ビットASCIIデータのみ |
| base64 | Base64エンコーディング |
| base64url | URLセーフなBase64エンコーディング |
| hex | 16進数エンコーディング |
| ucs2 | utf16leのエイリアス |
| binary | latin1のエイリアス(非推奨) |
例
const buf1 = Buffer.alloc(10); // ゼロ初期化されたBufferを作成
const buf2 = Buffer.from('hello'); // 文字列から作成
const buf3 = Buffer.from([1, 2, 3]); // 配列から作成
// 書き込みと読み取り
buf1.write('Node.js');
console.log(buf1.toString('utf8', 0, 6)); // 'Node.js'
// Bufferを比較
const bufA = Buffer.from('A');
const bufB = Buffer.from('B');
console.log(bufA.compare(bufB)); // -1
// Bufferを結合
const concatBuf = Buffer.concat([bufA, bufB]);