JavaScript | Web API:ファイル・データ操作 - FileReader

JavaScript JavaScript
スポンサーリンク

FileReader は「ファイルの中身を“いろんな形”で読み出すための専用リーダー」

前回の File API で出てきた File は、
「ユーザーが選んだファイルへのハンドル(取っ手)」でした。

でも、File だけでは中身は読めません。
「このファイルの中身を文字列で欲しい」「画像として表示したい」など、
具体的な形に変換してくれる存在が必要です。

その役割を担うのが FileReader です。

FileReader はざっくり言うと、

ファイル(File / Blob)の中身を
文字列として読む(readAsText)
画像などに使える data URL として読む(readAsDataURL)
バイナリとして読む(readAsArrayBuffer)

ための「非同期リーダー」です。

「非同期」というのがとても重要で、
読み込みが終わったタイミングでイベント(load など)が発火し、
そのときに reader.result に中身が入ります。


基本の流れ:「File を受け取る → FileReader で読む」

HTML でファイルを選ばせる

まずは、ユーザーにファイルを選んでもらいます。

<input type="file" id="fileInput">
<pre id="output"></pre>

JavaScript で FileReader を使う基本形

const input = document.querySelector("#fileInput");
const output = document.querySelector("#output");

input.addEventListener("change", () => {
  const file = input.files[0];
  if (!file) return;

  const reader = new FileReader();

  reader.addEventListener("load", () => {
    // 読み込み完了時、result に中身が入っている
    output.textContent = reader.result;
  });

  reader.addEventListener("error", () => {
    console.error("読み込みに失敗しました:", reader.error);
  });

  reader.readAsText(file, "utf-8");
});
JavaScript

ここで押さえてほしい重要ポイントは 2 つです。

1つ目は、読み込みは非同期 だということ。
readAsText を呼んだ瞬間にはまだ結果はありません。
読み込みが終わったときに load イベントが発火し、
そのタイミングで reader.result を使います。

2つ目は、読み方をメソッドで選ぶ ということ。
readAsText なのか readAsDataURL なのかで、
result の中身の「型」が変わります。


readAsText:テキストファイルを文字列として読む

テキスト読み込みの典型パターン

テキストファイル(.txt, .csv, .json など)を読みたいときは、
readAsText を使います。

const reader = new FileReader();

reader.addEventListener("load", () => {
  const text = reader.result; // string
  console.log("中身:", text);
});

reader.readAsText(file, "utf-8");
JavaScript

第2引数で文字コードを指定できます。
日本語環境だと、"utf-8" を指定しておくのが無難です。

例題:テキストファイルを読み込んで行ごとに表示する

HTML:

<input type="file" id="fileInput" accept=".txt">
<pre id="output"></pre>

JavaScript:

const input = document.querySelector("#fileInput");
const output = document.querySelector("#output");

input.addEventListener("change", () => {
  const file = input.files[0];
  if (!file) return;

  const reader = new FileReader();

  reader.addEventListener("load", () => {
    const text = reader.result;
    const lines = text.split("\n");
    output.textContent = lines.map((line, i) => `${i + 1}: ${line}`).join("\n");
  });

  reader.readAsText(file, "utf-8");
});
JavaScript

ここでの流れは、

File を受け取る
FileReader で readAsText する
load イベントで result を文字列として受け取る
split("\n") で行ごとに分割して表示する

という、とても素直なものです。

「FileReader は、File を“ただの文字列”に変えてくれる」と思うと、
一気にイメージしやすくなります。


readAsDataURL:画像プレビューの定番パターン

data URL とは何か

readAsDataURL を使うと、
ファイルの中身を data URL という形式の文字列に変換してくれます。

例えば画像なら、
data:image/png;base64,.... のような長い文字列です。

この文字列を <img>src に入れると、
そのまま画像として表示できます。

画像プレビューのコード

HTML:

<input type="file" id="fileInput" accept="image/*">
<img id="preview" alt="プレビュー" style="max-width: 200px;">

JavaScript:

const input = document.querySelector("#fileInput");
const img = document.querySelector("#preview");

input.addEventListener("change", () => {
  const file = input.files[0];
  if (!file) return;

  const reader = new FileReader();

  reader.addEventListener("load", () => {
    img.src = reader.result; // data URL が入る
  });

  reader.readAsDataURL(file);
});
JavaScript

ここでの重要ポイントは、

FileReader が「ファイル → data URL 文字列」に変換してくれる
その文字列を img.src に入れるだけでプレビューできる

というシンプルさです。

「アップロード前に画像を確認させたい」という要件では、
このパターンがほぼ定番になっています。


readAsArrayBuffer:バイナリとして扱いたいとき

バイナリデータをそのまま扱う

画像や音声、PDF などを
「自分でバイナリとして処理したい」場合は、
readAsArrayBuffer を使います。

const reader = new FileReader();

reader.addEventListener("load", () => {
  const buffer = reader.result; // ArrayBuffer
  console.log(buffer.byteLength);
});

reader.readAsArrayBuffer(file);
JavaScript

ArrayBuffer は「生のバイト列」を表すオブジェクトで、
TypedArray(Uint8Array など)と組み合わせて使います。

初心者のうちは、
「バイナリをガチで触るときに使うモード」くらいの理解で十分です。

テキストや画像プレビューが目的なら、
readAsTextreadAsDataURL だけでかなりのことができます。


FileReader が「イベント駆動」であることをしっかり理解する

なぜ同期ではなく非同期なのか

ファイル読み込みは、
サイズが大きくなると時間がかかります。

もし同期的(const result = reader.readAsText(file) みたいな形)だったら、
読み込みが終わるまでブラウザ全体が固まってしまいます。

それを避けるために、FileReader は 非同期+イベント という形になっています。

readAsTextreadAsDataURL を呼ぶ
読み込みがバックグラウンドで進む
終わったら load イベントが発火
そのときに reader.result を使う

という流れです。

よく使うイベント

最低限覚えておきたいのはこの 2 つです。

load
読み込みが正常に完了したとき

error
読み込み中にエラーが起きたとき

例えば、こんな書き方がよく使われます。

const reader = new FileReader();

reader.addEventListener("load", () => {
  console.log("成功:", reader.result);
});

reader.addEventListener("error", () => {
  console.error("失敗:", reader.error);
});

reader.readAsText(file, "utf-8");
JavaScript

大きなファイルで進捗バーを出したいときは、
progress イベントも使えますが、
最初のうちは loaderror だけで十分です。


例題:FileReader を Promise 化して async/await で使う(少し応用)

イベントリスナーで書くと、
ネストが増えて読みにくくなることがあります。

そこで、FileReader を Promise で包んでしまうテクニックがあります。

function readFileAsText(file, encoding = "utf-8") {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.addEventListener("load", () => {
      resolve(reader.result);
    });

    reader.addEventListener("error", () => {
      reject(reader.error);
    });

    reader.readAsText(file, encoding);
  });
}
JavaScript

これを使うと、こう書けます。

input.addEventListener("change", async () => {
  const file = input.files[0];
  if (!file) return;

  try {
    const text = await readFileAsText(file);
    console.log("中身:", text);
  } catch (err) {
    console.error("読み込み失敗:", err);
  }
});
JavaScript

「イベント駆動」を「async/await の世界」に持ち込むことで、
処理の流れが頭に入りやすくなります。

これは少し応用寄りですが、
FileReader の非同期性をより深く理解するのに役立ちます。


初心者として FileReader で本当に掴んでほしいこと

FileReader は「File / Blob の中身を読み込むためのリーダー」
読み込みは必ず非同期で、readAsText などを呼んだあとに load イベントで結果を受け取る
readAsText はテキスト用、readAsDataURL は画像プレビューなどに便利、readAsArrayBuffer はバイナリ処理用
結果は常に reader.result に入るが、そのタイミングは「load が発火したとき」
FileReader は「ユーザーが選んだファイル」に対してだけ使える(勝手にローカルを読むことはできない)

まずは次の 2 つを、自分の手で書いてみてください。

テキストファイルを選んで中身を <pre> に表示する(readAsText)
画像ファイルを選んで <img> にプレビュー表示する(readAsDataURL)

この 2 つがスムーズに書けるようになったとき、
FileReader は単なる API ではなく、
「ローカルのファイルと Web アプリをつなぐための、頼れる読書係」に見えてくるはずです。

タイトルとURLをコピーしました