🐥

「バイナリ」と「bytes」の違いをWebエンジニアが理解する - 曖昧さを解消する完全ガイド

に公開

はじめに

「CSVファイルをバイナリで送信」「ファイルサイズは1024bytes」

こういった表現を見て、「バイナリ」と「bytes」の使い分けに迷ったことはありませんか?

実は多くのWebエンジニアが、この2つの概念を曖昧に使っています。本記事では、その違いを明確にし、適切に使い分けられるようになることを目指します。

1. 一言で理解する違い

// バイナリ = 「どんな形式?」(表現方法)
const number = 65;
console.log(number.toString(2));  // "1000001" ← バイナリ表現

// bytes = 「どれくらい?」(データ量)
const text = "Hello";
console.log(new TextEncoder().encode(text).length);  // 5 ← 5bytes

覚え方:

  • バイナリ(Binary) = 形式・フォーマットの話
  • bytes = サイズ・単位の話

2. バイナリ(Binary)の理解

2.1 バイナリ = データの表現形式

// 同じデータの異なる表現
const value = 65;

// 10進数表現
console.log(value);              // 65

// 2進数表現(バイナリ)
console.log(value.toString(2));  // "1000001"

// 16進数表現
console.log(value.toString(16)); // "41"

// 文字表現
console.log(String.fromCharCode(value)); // "A"

2.2 「バイナリ形式」vs「テキスト形式」

Webエンジニアが最も遭遇する対比:

// ユーザーデータの例
const userData = {
  id: 123,
  name: "Alice",
  email: "alice@example.com"
};

// テキスト形式(JSON)
const textFormat = JSON.stringify(userData);
console.log(textFormat);
// '{"id":123,"name":"Alice","email":"alice@example.com"}'
// → 人間が読める

// バイナリ形式(Protocol Buffersを想定)
// [08 7B 12 05 41 6C 69 63 65 1A 11 61 6C 69 63 65 40 65 78 61 6D 70 6C 65 2E 63 6F 6D]
// → 人間には読めないが効率的

2.3 実務での「バイナリ」の使用例

// ファイル読み込みでの使い分け
const file = event.target.files[0];

// テキストとして読む
const textReader = new FileReader();
textReader.readAsText(file);        // テキスト形式

// バイナリとして読む
const binaryReader = new FileReader();
binaryReader.readAsArrayBuffer(file); // バイナリ形式

// APIレスポンスの処理
fetch('/api/data.json')
  .then(res => res.json());          // JSON(テキスト)形式

fetch('/api/image.png')
  .then(res => res.arrayBuffer());   // バイナリ形式

3. Bytes(バイト)の理解

3.1 Bytes = データサイズの単位

// 1 byte = 8 bits = 0〜255の値を表現可能

// 文字のbyte数を確認
console.log(new TextEncoder().encode("A").length);    // 1 byte
console.log(new TextEncoder().encode("あ").length);   // 3 bytes
console.log(new TextEncoder().encode("🎉").length);   // 4 bytes

// ファイルサイズの確認
const file = document.getElementById('fileInput').files[0];
console.log(`ファイルサイズ: ${file.size} bytes`);

3.2 なぜ「byte」という単位?

// bitだと細かすぎる
// 1文字 = 8 bits は扱いにくい

// byteにまとめることで
// 1文字 = 1 byte(ASCII)
// メモリアドレッシングも効率的

// 実例:色の表現
const red   = 255;  // 1 byte (8 bits)
const green = 128;  // 1 byte (8 bits)
const blue  = 0;    // 1 byte (8 bits)
// RGB合計 = 3 bytes

3.3 サイズ単位の階層

// 人間が読みやすいサイズ表示
function formatFileSize(bytes) {
  const units = ['bytes', 'KB', 'MB', 'GB'];
  let size = bytes;
  let unitIndex = 0;
  
  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024;
    unitIndex++;
  }
  
  return `${size.toFixed(2)} ${units[unitIndex]}`;
}

console.log(formatFileSize(1500));        // "1.46 KB"
console.log(formatFileSize(1048576));     // "1.00 MB"

4. 実際のコードでの使い分け

4.1 Protocol Buffersでの例

// .protoファイルでの定義
message FileData {
  string filename = 1;
  bytes content = 2;    // "bytes"型 = バイト配列を格納
  int64 size = 3;       // ファイルサイズ(bytes単位)
}
// 使用時の説明
// ✅ 正しい説明
"contentフィールドには、ファイルのバイナリデータを格納します"
"sizeフィールドには、ファイルサイズをbytes単位で格納します"

// ❌ 間違った説明
"contentフィールドには、ファイルのbytesデータを格納します"  // bytesは形式ではない
"sizeフィールドには、ファイルのバイナリサイズを格納します"  // バイナリは単位ではない

4.2 APIドキュメントでの使い分け

## ファイルアップロードAPI

### リクエスト仕様
- Method: POST
- Content-Type: multipart/form-data
- 最大ファイルサイズ: 10MB (10,485,760 bytes)

### レスポンス仕様
- 形式: JSON または バイナリ形式(Accept headerで指定)
- JSONの場合: Base64エンコードされたデータ
- バイナリの場合: 生のバイナリデータ

4.3 エラーメッセージでの使い分け

// ✅ 正しいエラーメッセージ
if (file.size > MAX_SIZE) {
  throw new Error(`ファイルサイズが上限(${MAX_SIZE} bytes)を超えています`);
}

if (!isBinaryFormat(file)) {
  throw new Error('バイナリ形式のファイルをアップロードしてください');
}

// ❌ 間違ったエラーメッセージ
"ファイルが10MBバイナリを超えています"      // バイナリは単位ではない
"100bytesフォーマットで送信してください"     // bytesは形式ではない

5. gRPC/ConnectRPCでの実例

5.1 Connect (JSON) vs Connect (Binary)

// この設定の意味を正確に理解する
const transport = createConnectTransport({
  baseUrl: "http://localhost:8080",
  useBinaryFormat: false,  // false = JSON形式, true = バイナリ形式
});

// 実際の通信
// JSON形式の場合
POST /api.UserService/GetUser
Content-Type: application/json
Content-Length: 15 bytes        // サイズはbytes単位

{"id": "123"}                   // データはJSON形式

// バイナリ形式の場合
POST /api.UserService/GetUser
Content-Type: application/connect+proto
Content-Length: 5 bytes         // サイズはbytes単位

[08 7B]                         // データはバイナリ形式

5.2 パフォーマンス比較での表現

// 測定結果の正しい表現
const results = {
  jsonFormat: {
    size: "125KB",           // サイズ(bytes系単位)
    format: "JSON",          // 形式
    parseTime: "3.2ms"
  },
  binaryFormat: {
    size: "45KB",            // サイズ(bytes系単位)
    format: "Protocol Buffers", // 形式
    parseTime: "1.1ms"
  }
};

// ✅ 正しい説明
"バイナリ形式の方が、JSONより64%小さいサイズで転送できます"

// ❌ 間違った説明
"bytes形式の方が効率的です"  // bytesは形式ではない

6. よくある間違いと正しい使い方

6.1 会話での間違い

// ❌ よくある間違い
"データを100バイナリ送信します"         // バイナリは単位ではない
"このAPIはbytes形式を返します"          // bytesは形式ではない
"バイナリサイズは1KBです"              // 「バイナリデータのサイズ」が正しい

// ✅ 正しい表現
"100bytesのデータを送信します"
"このAPIはバイナリ形式でデータを返します"
"バイナリデータのサイズは1KBです"

6.2 コメントでの使い分け

/**
 * 画像ファイルを処理する関数
 * 
 * @param {File} imageFile - 処理する画像ファイル
 * @param {Object} options - オプション設定
 * @param {boolean} options.returnBinary - trueの場合バイナリ形式で返す
 * @param {number} options.maxSizeBytes - 最大ファイルサイズ(bytes)
 * 
 * @returns {Promise<string|ArrayBuffer>} 
 *          Base64文字列(テキスト形式)またはArrayBuffer(バイナリ形式)
 */
async function processImage(imageFile, options = {}) {
  // ファイルサイズチェック(bytes単位)
  if (imageFile.size > options.maxSizeBytes) {
    throw new Error(`ファイルサイズが上限を超えています`);
  }
  
  // バイナリデータとして読み込み
  const binaryData = await imageFile.arrayBuffer();
  
  // 返却形式の選択
  if (options.returnBinary) {
    return binaryData;  // バイナリ形式で返す
  } else {
    // Base64(テキスト形式)に変換して返す
    return btoa(String.fromCharCode(...new Uint8Array(binaryData)));
  }
}

7. 実践的なデバッグ

7.1 Chrome DevToolsでの確認

// Networkタブでの見方

// ヘッダー情報
Content-Type: application/octet-stream  // バイナリ形式
Content-Length: 2048                    // 2048 bytes

// Responseタブ
// テキスト形式 → 内容が表示される
// バイナリ形式 → [Binary content] と表示

// Sizeカラム
// 常にbytes系の単位で表示(1.5 KB, 324 B など)

7.2 ログ出力のベストプラクティス

// デバッグログの正しい書き方
function logDataInfo(data) {
  const bytes = new TextEncoder().encode(JSON.stringify(data));
  
  console.log({
    format: "JSON",                    // 形式
    size: `${bytes.length} bytes`,     // サイズ
    preview: data                      // 内容
  });
  
  // バイナリ表現も確認したい場合
  console.log({
    binaryRepresentation: Array.from(bytes).map(b => 
      b.toString(16).padStart(2, '0')
    ).join(' ')
  });
}

まとめ:正しい使い分けのための指針

クイックリファレンス

文脈 バイナリ(Binary) Bytes
データ形式の説明 "バイナリ形式で保存" ✅ "bytes形式で保存" ❌
データサイズの説明 "100バイナリ" ❌ "100 bytes" ✅
対比表現 "JSONではなくバイナリ" ✅ "KBではなくbytes" ✅
エラーメッセージ "バイナリ形式が不正" ✅ "10MB以下にしてください" ✅

最終チェックリスト

// 自分の文章をチェック
const checkUsage = (text) => {
  // ❌ NGパターン
  const ngPatterns = [
    /\d+\s*バイナリ/,        // "100バイナリ"
    /bytes形式/,             // "bytes形式"
    /バイナリサイズ/,        // "バイナリサイズ"(単独使用)
  ];
  
  // ✅ OKパターン
  const okPatterns = [
    /バイナリ形式/,          // 形式の話
    /\d+\s*bytes/,          // サイズの話
    /バイナリデータ/,        // データの話
  ];
};

これらの違いを意識することで、技術文書やコードコメントがより正確で伝わりやすくなります。特にgRPCやファイル処理を扱う際は、この使い分けが重要です!

Discussion