「ローカルの .txt
をブラウザだけで読み込んで中身をサッと確認したい」「サーバーに置いた log.csv
を JavaScript で取得してリアルタイム表示したい」――そんなシンプルな要望でも、FileReader・fetch・CORS・文字化けなど壁は意外と多いものです。「とりあえず動くサンプル」はネット上に点在していますが、ローカル・サーバー両方を網羅し、かつエンコーディングや配列化まで“一気通貫”で学べる記事はなかなか見つかりません。そこで本記事では、最小構成のコピペコードから応用テクニック、そしてトラブルシューティングまでをまとめて解説します。これを読めば、テキストファイル読み込みにまつわる迷いが一掃されるはずです。
JavaScriptでテキストファイルを読み込む基本!ブラウザ・サーバーからの読み込みを完全解説
Webアプリケーション開発において、ユーザーがPC内のファイルをアップロードしたり、サーバー上の設定ファイルを読み込んだりする機能は非常に重要です。本記事では、JavaScriptでテキストファイルを読み込むための基本的な方法から、実践的なテクニック、そしてよくある問題とその解決策まで、Webエンジニアの皆さんが知りたい情報を網羅的に解説します。これを読めば、もうテキストファイルの読み込みで迷うことはありません。

JavaScriptでローカルテキストファイルを読み込む2つの方法【FileReader/showOpenFilePicker】
ユーザーが自分のPCに保存しているテキストファイルをJavaScriptで読み込むには、主にFileReader API
とshowOpenFilePicker API
という2つの方法があります。
FileReader APIによる読み込み
FileReader API
は、ユーザーがHTMLの<input type="file">
要素を使って選択したファイルの内容を非同期で読み込むためのインターフェースです。対応ブラウザも広く、多くのWebアプリケーションで利用されています。
以下は、FileReader API
を使ってローカルのテキストファイルを読み込み、その内容をコンソールに表示する基本的なコード例です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FileReader API テキストファイル読み込み</title>
</head>
<body>
<h1>FileReader APIでテキストファイルを読み込む</h1>
<input type="file" id="fileInput" accept=".txt">
<pre id="fileContent"></pre>
<script>
document.getElementById('fileInput').addEventListener('change', function(e) {
const file = e.target.files[0]; // 選択されたファイルを取得
if (file) {
const reader = new FileReader(); // FileReaderオブジェクトを作成
// ファイル読み込みが完了した時のイベントハンドラ
reader.onload = function(event) {
const content = event.target.result; // ファイルの内容を取得
document.getElementById('fileContent').textContent = content;
console.log('ファイルの内容:', content);
};
// ファイル読み込み中にエラーが発生した時のイベントハンドラ
reader.onerror = function() {
console.error('ファイルの読み込み中にエラーが発生しました。');
};
// ファイルをテキストとして読み込む
reader.readAsText(file, 'UTF-8'); // 第二引数で文字コードを指定可能
} else {
document.getElementById('fileContent').textContent = 'ファイルが選択されていません。';
}
});
</script>
</body>
</html>
このコードでは、<input type="file" id="fileInput" accept=".txt">
でファイル選択ボタンを作成し、ユーザーがファイルを選択するとchange
イベントが発火します。イベントリスナー内でFileReader
のインスタンスを作成し、readAsText()
メソッドでファイルをテキストとして読み込んでいます。読み込みが完了するとonload
イベントが発火し、event.target.result
からファイルの内容を取得できます。
readAsText()
の第二引数では、読み込むファイルの**文字コード(エンコーディング)**を指定できます。通常は'UTF-8'
を指定しますが、後述する文字化け対策で詳しく解説します。

showOpenFilePicker APIによる読み込み
showOpenFilePicker API
は、より高度なファイルシステムアクセスを可能にする新しいAPIで、ユーザーがファイルを選択するダイアログを直接開くことができます。FileReader
よりも強力で、ファイルの保存なども可能ですが、まだすべてのブラウザで完全にサポートされているわけではありません(対応状況を確認することが重要です)。
以下は、showOpenFilePicker API
を使った基本的な読み込み例です。
// showOpenFilePicker API を使用したテキストファイル読み込み
async function readFileWithPicker() {
try {
// ファイル選択ダイアログを開く
const [fileHandle] = await window.showOpenFilePicker({
types: [{
description: 'Text Files',
accept: { 'text/plain': ['.txt'] }
}],
multiple: false // 複数ファイル選択を許可しない
});
// ファイルの内容を取得
const file = await fileHandle.getFile();
const content = await file.text(); // ファイルの内容をテキストとして取得
document.getElementById('fileContent').textContent = content;
console.log('ファイルの内容:', content);
} catch (err) {
console.error('ファイルの選択または読み込みがキャンセル/失敗しました:', err);
document.getElementById('fileContent').textContent = 'ファイルの読み込みに失敗しました。';
}
}
// HTMLにボタンを追加してこの関数を呼び出す
// <button onclick="readFileWithPicker()">ファイルを選択(showOpenFilePicker)</button>
showOpenFilePicker
は非同期処理であり、async/await
構文と組み合わせて使われます。よりモダンで強力なAPIですが、現状では互換性を考慮しFileReader
が広く使われています。

次に、HTMLとJavaScriptだけで完結する、より実践的なファイル選択と内容表示のデモを見ていきましょう。
HTMLとJavaScriptだけで完結!ファイル選択・内容表示の最小構成サンプルコード
ここでは、ユーザーがPCからテキストファイルを選択し、その内容をWebページ上の特定の<div>
要素に即座に表示する、最もシンプルで実用的な例を紹介します。サーバーサイドの処理は一切不要で、ブラウザだけで完結します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>テキストファイル読み込みデモ</title>
<style>
body { font-family: sans-serif; margin: 20px; }
#fileInput { margin-bottom: 10px; }
#outputArea {
border: 1px solid #ccc;
padding: 15px;
min-height: 150px;
background-color: #f9f9f9;
white-space: pre-wrap; /* 改行とスペースを保持 */
word-break: break-all; /* 長い単語でも折り返す */
}
</style>
</head>
<body>
<h1>JavaScriptでテキストファイルを読み込んで表示</h1>
<p>ローカルPCからテキストファイルを選択してください。</p>
<input type="file" id="txtFileInput" accept=".txt, .csv, .log">
<p>ファイル内容:</p>
<div id="outputArea">
ここにファイルの内容が表示されます。
</div>
<script>
// HTML要素の取得
const txtFileInput = document.getElementById('txtFileInput');
const outputArea = document.getElementById('outputArea');
// ファイルが選択された時の処理
txtFileInput.addEventListener('change', (event) => {
const file = event.target.files[0]; // 選択されたファイルオブジェクトを取得
// ファイルが選択されなかった場合
if (!file) {
outputArea.textContent = 'ファイルが選択されていません。';
return;
}
// FileReaderインスタンスの作成
const reader = new FileReader();
// ファイル読み込み完了時のイベントハンドラ
reader.onload = (e) => {
const fileContent = e.target.result; // 読み込まれたテキストデータ
outputArea.textContent = fileContent; // outputAreaに表示
};
// ファイル読み込みエラー時のイベントハンドラ
reader.onerror = (e) => {
console.error('ファイル読み込みエラー:', e.target.error);
outputArea.textContent = 'ファイルの読み込み中にエラーが発生しました。';
};
// ファイルをテキストとして読み込む
reader.readAsText(file, 'UTF-8'); // UTF-8エンコーディングで読み込み
});
</script>
</body>
</html>
このサンプルコードでは、input type="file"
でユーザーがファイルを選択すると、そのchange
イベントを検知してFileReader
が起動します。reader.onload
内でファイルの内容を取得し、outputArea
(div
要素) のtextContent
に設定することで、画面に内容が表示されます。非常にシンプルながら、Webアプリケーションにおけるファイル読み込みの基本的な形となります。
サーバー上のテキストファイルをJavaScriptで読み込むには?fetch APIの基本
Webサーバー上にあるテキストファイル(設定ファイル、CSVデータ、JSONデータなど)をJavaScriptで読み込む場合は、主にfetch API
を使用します。fetch API
は、ネットワークリソースを取得するための最新かつ強力なインターフェースであり、Promiseベースで非同期処理をより簡潔に記述できます。



fetch APIを使ったテキストファイルの読み込み
fetch
APIは、指定したURLからリソースを取得し、そのレスポンスをPromiseとして返します。テキストファイルの場合、レスポンスオブジェクトのtext()
メソッドを使うことで、ファイルの内容をテキスト形式で取得できます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>fetch API テキストファイル読み込み</title>
<style>
body { font-family: sans-serif; margin: 20px; }
#serverFileContent {
border: 1px solid #ccc;
padding: 15px;
min-height: 100px;
background-color: #f0f8ff;
white-space: pre-wrap;
}
</style>
</head>
<body>
<h1>サーバー上のテキストファイルを読み込む (fetch API)</h1>
<button id="loadServerFileBtn">サーバーのファイルを読み込む</button>
<p>サーバーファイル内容:</p>
<div id="serverFileContent">
ここにサーバー上のファイルの内容が表示されます。
</div>
<script>
// サーバー上に存在する架空のテキストファイルパス(例: data.txt)
// 実際には、Webサーバーのルートディレクトリなどに `data.txt` を配置してください
const SERVER_FILE_URL = 'data.txt';
const loadBtn = document.getElementById('loadServerFileBtn');
const contentDiv = document.getElementById('serverFileContent');
loadBtn.addEventListener('click', async () => {
try {
// fetch APIを使ってサーバーからテキストファイルを取得
const response = await fetch(SERVER_FILE_URL);
// レスポンスが正常かチェック
if (!response.ok) {
throw new Error(`HTTPエラー: ${response.status}`);
}
// レスポンスボディをテキストとして取得
const fileContent = await response.text();
contentDiv.textContent = fileContent;
console.log('サーバーファイルの内容:', fileContent);
} catch (error) {
console.error('サーバーファイルの読み込みに失敗しました:', error);
contentDiv.textContent = `エラー: サーバーファイルの読み込みに失敗しました。詳細: ${error.message}`;
}
});
</script>
</body>
</html>
この例では、SERVER_FILE_URL
に指定したパス(例えばWebサーバーのルートに置かれたdata.txt
)をfetch
で取得しています。await response.text()
で取得したテキストデータをcontentDiv
に表示しています。fetch
はPromiseを返すため、async/await
構文を使うことで、非同期処理を同期処理のように記述でき、可読性が高まります。
XMLHttpRequest (XHR) を使った従来の読み込み方法
fetch API
がモダンな方法ですが、古いブラウザのサポートや、特定の要件からXMLHttpRequest
(通称XHR) を使用するケースもまだあります。
// XMLHttpRequest を使用したテキストファイル読み込み(参考)
function loadFileWithXHR(url, callback) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true); // trueで非同期
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // リクエストが完了
if (xhr.status === 200) { // 正常にレスポンスを受け取った
callback(null, xhr.responseText);
} else {
callback(new Error(`XHRエラー: ${xhr.status}`));
}
}
};
xhr.onerror = function() {
callback(new Error('ネットワークエラー'));
};
xhr.send();
}
// 使用例:
// loadFileWithXHR('data.txt', (error, content) => {
// if (error) {
// console.error(error);
// } else {
// document.getElementById('serverFileContent').textContent = content;
// }
// });
XMLHttpRequest
はコールバックベースのAPIであり、Promiseベースのfetch
と比較するとコードが複雑になりがちです。特別な理由がない限り、新規開発ではfetch API
を使用することが推奨されます。
読み込んだテキストファイルを思い通りに加工・表示する方法
テキストファイルを読み込むだけでは、多くの場合、目的は達成できません。読み込んだデータを加工したり、特定の形式に変換したり、Webページに整形して表示したりするステップが不可欠です。ここでは、読み込んだテキストデータを最大限に活用するための実践的な方法を解説します。

テキストファイルを1行ずつ読み込み!配列として扱う split('\n') の活用例
読み込んだテキストファイルが複数行にわたるデータ(例:ログファイル、CSVファイルの一部)である場合、各行を個別に処理したいケースが多くあります。JavaScriptでは、split('\n')
メソッドを使うことで、テキストを改行コードで分割し、各行を要素とする配列に簡単に変換できます。
// 読み込んだテキストデータの例
const rawText = `Apple
Banana
Orange
Grape
`;
// 1行ずつ配列として分割
let lines = rawText.split('\n');
console.log('元の配列:', lines); // ["Apple", "Banana", "Orange", "Grape", ""]
// 不要な空白行や空要素を削除する場合
lines = lines.map(line => line.trim()).filter(line => line !== '');
console.log('整形後の配列:', lines); // ["Apple", "Banana", "Orange", "Grape"]
// ファイル読み込みと組み合わせる例
// 以下のコードは、前述のFileReaderのonloadイベント内で利用できます。
/*
reader.onload = (e) => {
const fileContent = e.target.result;
const lines = fileContent.split('\n').map(line => line.trim()).filter(line => line !== '');
console.log('読み込んだテキストを1行ずつ配列に:', lines);
// ここでlines配列を使ってさらに処理を行う
};
*/
split('\n')
で分割すると、テキストの最後に改行がある場合、最後の要素が空文字列になることがあります。map(line => line.trim())
で各行の前後にある空白(改行コード含む)を削除し、filter(line => line !== '')
で空の要素を除外することで、よりクリーンな配列が得られます。
読み込んだテキストデータをJavaScriptの変数に格納して再利用する
読み込んだテキストファイルの内容は、一時的に表示するだけでなく、JavaScriptの内部で変数として保持し、様々な処理に再利用することが一般的です。
let loadedData = ''; // ファイル内容を格納する変数
// FileReaderの場合
document.getElementById('fileInput').addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(event) {
loadedData = event.target.result; // ファイル内容を変数に格納
console.log('変数に格納されたデータ:', loadedData);
// ここで loadedData を使って他の処理を呼び出す
processLoadedData(loadedData);
};
reader.readAsText(file);
}
});
// fetch APIの場合
async function fetchAndStoreData(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error('Network response was not ok.');
loadedData = await response.text(); // ファイル内容を変数に格納
console.log('変数に格納されたデータ:', loadedData);
// ここで loadedData を使って他の処理を呼び出す
processLoadedData(loadedData);
} catch (error) {
console.error('データ取得エラー:', error);
}
}
function processLoadedData(data) {
// 例: 読み込んだデータを全て大文字にする
const upperCaseData = data.toUpperCase();
console.log('処理されたデータ:', upperCaseData);
// さらにHTML要素に表示するなど
document.getElementById('processedOutput').textContent = upperCaseData;
}
// <div id="processedOutput"></div>
// <button onclick="fetchAndStoreData('data.txt')">サーバーから読み込む</button>
このように、グローバル変数や、特定のスコープ内の変数に読み込んだデータを格納することで、その後の関数やイベントでデータを自由に加工・利用できるようになります。
CSV/TSV/JSONファイルを読み込んでパース!JavaScriptオブジェクトへの変換術
テキストファイルには、CSV (Comma Separated Values) や TSV (Tab Separated Values) のように構造化されたデータ、あるいはJSON (JavaScript Object Notation) のように直接JavaScriptオブジェクトに変換できる形式もあります。これらのファイルを読み込んで、JavaScriptで扱いやすいデータ構造に変換する方法を見ていきましょう。

CSV/TSVファイルのパース
CSVやTSVは、スプレッドシートのデータをテキスト形式で保存したものです。JavaScriptの文字列操作メソッドを使って、シンプルなCSV/TSVなら簡単にパースできます。
// CSVデータ例
const csvData = `Name,Age,City
Alice,30,New York
Bob,24,London
Charlie,35,Paris
`;
function parseCSV(csvText) {
const lines = csvText.trim().split('\\n'); // 空白行を削除
const headers = lines[0].split(','); // ヘッダー行をカンマで分割
const data = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(','); // 各行をカンマで分割
const row = {};
headers.forEach((header, index) => {
row[header.trim()] = values[index].trim(); // ヘッダーをキーにしてオブジェクトに格納
});
data.push(row);
}
return data;
}
const parsedCsv = parseCSV(csvData);
console.log('パースされたCSVデータ:', parsedCsv);
/*
[
{ Name: "Alice", Age: "30", City: "New York" },
{ Name: "Bob", Age: "24", City: "London" },
{ Name: "Charlie", Age: "35", City: "Paris" }
]
*/
// TSVも同様に、split('\\t') を使えばパースできます。
このparseCSV
関数は、最初の行をヘッダーとして扱い、それ以降の行をデータとしてオブジェクトの配列に変換します。より複雑なCSV(引用符や改行を含む場合)には専用のライブラリ(Papa Parseなど)の利用を検討してください。
JSONファイルのパース
JSONはJavaScriptと非常に親和性が高く、JSON.parse()
メソッドを使うだけで簡単にJavaScriptオブジェクトに変換できます。
// JSONデータ例 (文字列として読み込まれた場合)
const jsonString = `[
{ "id": 1, "product": "Laptop", "price": 1200 },
{ "id": 2, "product": "Mouse", "price": 25 },
{ "id": 3, "product": "Keyboard", "price": 75 }
]`;
try {
const jsonObject = JSON.parse(jsonString);
console.log('パースされたJSONデータ:', jsonObject);
/*
[
{ id: 1, product: "Laptop", price: 1200 },
{ id: 2, product: "Mouse", price: 25 },
{ id: 3, product: "Keyboard", price: 75 }
]
*/
} catch (error) {
console.error('JSONパースエラー:', error);
}
// fetch APIでJSONファイルを読み込む場合
async function fetchAndParseJson(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error('Network response was not ok.');
const jsonContent = await response.json(); // .json()メソッドで直接JSONオブジェクトに変換
console.log('fetchで取得したJSONデータ:', jsonContent);
return jsonContent;
} catch (error) {
console.error('JSONファイルの取得・パースエラー:', error);
}
}
// 例: fetchAndParseJson('products.json'); // サーバー上のproducts.jsonを読み込む
fetch API
でJSONを読み込む場合、レスポンスオブジェクトのjson()
メソッドを使うと、テキストとして取得してからJSON.parse()
する必要がなく、より簡潔に処理できます。
読み込んだテキストをHTMLの<textarea>や<div>に表示する具体的な手順
読み込んだテキストデータをWebページ上に表示する方法は多岐にわたりますが、最も一般的なのは<textarea>
や<div>
要素を利用することです。
<textarea>
: ユーザーが編集可能なテキストエリアに表示する場合に最適です。ファイルの内容をそのまま入力フィールドにしたい場合に便利です。<div>
または<pre>
: 単に内容を表示するだけで、編集させたくない場合に適しています。特に<pre>
要素は、テキストの改行やスペースをそのまま保持して表示するため、コードやログの表示に役立ちます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>テキスト表示例</title>
</head>
<body>
<h1>読み込んだテキストの表示例</h1>
<input type="file" id="fileToDisplay" accept=".txt">
<h2>textareaに表示</h2>
<textarea id="outputTextArea" rows="10" cols="50"></textarea>
<h2>div (pre) に表示</h2>
<pre id="outputPre"></pre>
<script>
const fileToDisplay = document.getElementById('fileToDisplay');
const outputTextArea = document.getElementById('outputTextArea');
const outputPre = document.getElementById('outputPre');
fileToDisplay.addEventListener('change', (event) => {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
const content = e.target.result;
// textareaに表示
outputTextArea.value = content; // <textarea>には.valueを使う
// pre要素に表示
outputPre.textContent = content; // <pre>や<div>には.textContentを使う
};
reader.readAsText(file, 'UTF-8');
});
</script>
</body>
</html>
textarea
要素に表示する場合はvalue
プロパティを、div
やpre
要素に表示する場合はtextContent
プロパティを使用します。innerHTML
も使えますが、セキュリティ上のリスク(XSS攻撃など)を避けるため、純粋なテキストを表示するだけであればtextContent
の使用が推奨されます。
整形されたデータ(例:CSVから変換した表)をHTMLにレンダリングする
CSVやJSONからパースしたデータをHTMLの表 (<table>
) やリスト (<ul>
) として表示することで、ユーザーにとってより分かりやすい形で情報を提供できます。
<input type="file" id="csvFileInput" accept=".csv">
<div id="tableOutput"></div>
<script>
document.getElementById('csvFileInput').addEventListener('change', async (event) => {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
const csvText = e.target.result;
const data = parseCSV(csvText); // 前述のparseCSV関数を使用
// テーブルを生成して表示
let tableHtml = '<table><thead><tr>';
// ヘッダーを生成
Object.keys(data[0]).forEach(header => {
tableHtml += `<th>${header}</th>`;
});
tableHtml += '</tr></thead><tbody>';
// データ行を生成
data.forEach(row => {
tableHtml += '<tr>';
Object.values(row).forEach(value => {
tableHtml += `<td>${value}</td>`;
});
tableHtml += '</tr>';
});
tableHtml += '</tbody></table>';
document.getElementById('tableOutput').innerHTML = tableHtml; // innerHTMLでHTML文字列を挿入
};
reader.readAsText(file, 'UTF-8');
});
</script>
このように、JavaScriptでHTML要素を動的に生成し、innerHTML
プロパティを使ってDOMに挿入することで、パースしたデータをリッチな形式で表示できます。
複数ファイルを同時に読み込む方法とドラッグ&ドロップ実装
ユーザーが複数のファイルを一度に選択したり、ファイルをWebページにドラッグ&ドロップしたりして読み込めるようにすると、アプリケーションのユーザビリティが向上します。
input type="file"
での複数ファイル選択
<input type="file">
要素にmultiple
属性を追加するだけで、ユーザーはファイル選択ダイアログで複数のファイルを選択できるようになります。JavaScript側では、event.target.files
がファイルオブジェクトのFileList
(配列のようなオブジェクト)として取得できます。
<input type="file" id="multipleFileInput" multiple accept=".txt">
<div id="multipleFilesOutput"></div>
<script>
document.getElementById('multipleFileInput').addEventListener('change', async (event) => {
const files = event.target.files; // 選択された全ファイル
if (files.length === 0) {
document.getElementById('multipleFilesOutput').textContent = 'ファイルが選択されていません。';
return;
}
let allContents = '';
for (const file of files) {
// 各ファイルをFileReaderで読み込む
const reader = new FileReader();
await new Promise((resolve, reject) => {
reader.onload = (e) => {
allContents += `--- ${file.name} ---\\n${e.target.result}\\n\\n`;
resolve();
};
reader.onerror = reject;
reader.readAsText(file, 'UTF-8');
});
}
document.getElementById('multipleFilesOutput').textContent = allContents;
});
</script>
複数のファイルを非同期で読み込むため、Promise
とasync/await
を組み合わせて、各ファイルの読み込みが完了するのを待ってから次の処理に進むようにしています。
ドラッグ&ドロップによるファイル読み込み
ドラッグ&ドロップによるファイル読み込みは、ユーザーにとって直感的な操作性を提供します。これは、dragover
、dragleave
、drop
などのイベントを利用して実現します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ドラッグ&ドロップファイル読み込み</title>
<style>
#dropArea {
width: 300px;
height: 150px;
border: 2px dashed #ccc;
text-align: center;
line-height: 150px;
font-size: 1.2em;
color: #666;
}
#dropArea.highlight {
border-color: #007bff;
background-color: #e0f2f7;
}
</style>
</head>
<body>
<h1>ファイルをドラッグ&ドロップで読み込む</h1>
<div id="dropArea">
ファイルをここにドラッグ&ドロップしてください
</div>
<pre id="dndOutput"></pre>
<script>
const dropArea = document.getElementById('dropArea');
const dndOutput = document.getElementById('dndOutput');
// デフォルトのブラウザの挙動をキャンセル(ファイルが開かれるのを防ぐ)
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
// ドラッグ中のスタイル変更
['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, () => dropArea.classList.add('highlight'), false);
});
['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, () => dropArea.classList.remove('highlight'), false);
});
// ドロップ時の処理
dropArea.addEventListener('drop', async (e) => {
const dt = e.dataTransfer;
const files = dt.files; // ドロップされたファイルリスト
if (files.length === 0) {
dndOutput.textContent = 'ファイルがドロップされませんでした。';
return;
}
let allContents = '';
for (const file of files) {
// ファイルタイプを確認(例: テキストファイルのみ許可)
if (file.type && !file.type.startsWith('text/')) {
allContents += `--- ${file.name} --- (テキストファイルではありません)\\n\\n`;
continue;
}
const reader = new FileReader();
await new Promise((resolve, reject) => {
reader.onload = (event) => {
allContents += `--- ${file.name} ---\\n${event.target.result}\\n\\n`;
resolve();
};
reader.onerror = reject;
reader.readAsText(file, 'UTF-8');
});
}
dndOutput.textContent = allContents;
}, false);
</script>
</body>
</html>
ドラッグ&ドロップの実装では、ブラウザのデフォルト挙動をpreventDefault()
で停止し、drop
イベントでe.dataTransfer.files
からドロップされたファイルを取得します。デザイン面では、ドラッグ中のハイライト表示なども加えることで、ユーザーに分かりやすいUIを提供できます。
JavaScriptテキストファイル読み込みでよくある問題と解決策
JavaScriptでテキストファイルを読み込む際には、文字化けやセキュリティ制約、パスの指定方法など、いくつかの一般的な問題に直面することがあります。ここでは、それらの問題への対処法と、より堅牢な実装のためのヒントを提供します。

文字化けはこれで解決!Shift-JISやUTF-8のエンコーディング指定と注意点
テキストファイルを読み込んだ際に、日本語などが正しく表示されずに「文字化け」する問題はよく発生します。これは、ファイルの文字コード(エンコーディング)と、JavaScriptが読み込む際に指定するエンコーディングが一致しない場合に起こります。
FileReader.readAsText()
のエンコーディング指定
FileReader.readAsText()
メソッドは、第二引数にエンコーディングを指定できます。これを正しく設定することが文字化け対策の基本です。
// 例: Shift-JISのファイルを読み込む場合
reader.readAsText(file, 'Shift_JIS');
// 例: EUC-JPのファイルを読み込む場合
reader.readAsText(file, 'EUC-JP');
// 例: UTF-8(BOMなし)のファイルを読み込む場合
reader.readAsText(file, 'UTF-8');
ファイルがどの文字コードで保存されているか分からない場合は、いくつかのエンコーディングを試してみるか、ユーザーにエンコーディングを選択させるUIを提供することも検討できます。
BOM (Byte Order Mark) が原因の文字化けと対処法
UTF-8には、ファイルの先頭にBOM(バイトオーダーマーク)が付与されている場合があります。このBOMが原因で、テキストの先頭に不要な文字が表示されたり、JSONのパースに失敗したりすることがあります。
BOM付きUTF-8ファイルを読み込んだ場合、trim()
や特定の文字を削除する処理で対応できます。
reader.onload = (e) => {
let content = e.target.result;
// BOM(UTF-8の場合)を削除する正規表現
if (content.charCodeAt(0) === 0xFEFF) {
content = content.substring(1);
}
// または、より汎用的なtrim()を使う
// content = content.trim();
console.log('BOM削除後の内容:', content);
document.getElementById('fileContent').textContent = content;
};
理想的には、ファイル保存時にBOMを付与しない設定で保存することが推奨されます。
ファイル読み込み時のエラー処理とセキュリティ対策(CORS/File API制限)
安全で安定したアプリケーションを開発するためには、ファイル読み込み時のエラー処理と、ブラウザのセキュリティ制約への理解が不可欠です。
エラー処理の基本
FileReader
やfetch API
は非同期処理であるため、エラーが発生する可能性があります。try...catch
ブロックやPromiseの.catch()
メソッドを使って、適切にエラーを捕捉し、ユーザーに分かりやすいメッセージを表示することが重要です。
// FileReaderのエラー処理
reader.onerror = function(event) {
console.error('FileReaderエラー:', event.target.error.name);
alert('ファイルの読み込み中にエラーが発生しました。ファイルが破損しているか、アクセス権限がありません。');
};
// fetch APIのエラー処理
try {
const response = await fetch(url);
if (!response.ok) { // HTTPステータスが200番台以外の場合
throw new Error(`HTTPエラー: ${response.status} ${response.statusText}`);
}
const data = await response.text();
// 処理
} catch (error) {
console.error('fetchエラー:', error);
alert('サーバーからのファイル取得に失敗しました。URLを確認してください。');
}
CORS (Cross-Origin Resource Sharing) の制約
fetch API
やXMLHttpRequest
を使って、異なるオリジン(ドメイン、プロトコル、ポートのいずれかが異なる)のサーバーからファイルを読み込もうとすると、CORS(Cross-Origin Resource Sharing)のセキュリティ制約によりブロックされることがあります。
この問題は、ファイルを提供するサーバー側で適切なCORSヘッダー(例: Access-Control-Allow-Origin: *
または特定のオリジン)を設定することで解決できます。クライアントサイド(JavaScript)からCORSを回避する方法はありません。サーバー側の協力が必要です。

File APIのセキュリティ上の制限
FileReader
を含むFile APIは、ユーザーのローカルファイルシステムへの無制限なアクセスを防ぐため、セキュリティ上の制限があります。
- ユーザー操作が必須: 通常、
input type="file"
によるファイル選択や、ドラッグ&ドロップといったユーザーの明示的な操作がなければ、JavaScriptからローカルファイルにアクセスすることはできません。 - 読み込み専用: JavaScriptからローカルファイルを直接作成したり、既存のファイルを上書きしたりすることはできません(
showSaveFilePicker
などの一部APIを除く)。
これらの制限は、ユーザーのプライバシーとセキュリティを守るために設けられています。
相対パス・絶対パスでのファイル指定は?開発環境と本番環境での違い
Webサーバー上のテキストファイルをfetch API
などで読み込む際、そのファイルのパスをどのように指定するかは重要です。
- 絶対パス: Webサイトのルートからの完全なパス。例:
/data/config.json
(ドメインは含まない)。 - 相対パス: 現在のHTMLファイルからの相対的な位置。例:
./data/config.json
(現在のディレクトリ内のdata
フォルダ)。
開発環境 vs. 本番環境:
- 開発環境: ローカルのファイルシステムで直接HTMLファイルを開いている場合、
fetch
はfile://
プロトコルで動作しようとするため、多くの場合CORSエラーやセキュリティエラーが発生します。このため、開発時には簡易的なローカルサーバー(例:npm install -g http-server
)を立てて作業することが推奨されます。 - 本番環境: 常にWebサーバー上で動作するため、上記のように絶対パスや相対パスでファイルを指定し、
fetch
で読み込むことができます。
// 現在のHTMLからの相対パスで指定
const RELATIVE_PATH_URL = './assets/settings.txt';
// ドメインルートからの絶対パスで指定
// 例: <https://example.com/api/data.json>
const ABSOLUTE_PATH_URL = '/api/data.json';
async function loadTextFile(path) {
try {
const response = await fetch(path);
if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);
const content = await response.text();
console.log(`ファイル (${path}) の内容:`, content);
} catch (error) {
console.error(`ファイル (${path}) の読み込みに失敗しました:`, error);
}
}
// loadTextFile(RELATIVE_PATH_URL);
// loadTextFile(ABSOLUTE_PATH_URL);
ファイルパスの指定は、サーバー側のファイル配置と密接に関連しているため、開発環境と本番環境での挙動の違いを理解しておくことが重要です。
空ファイルやBOM付きファイルも安心!特殊ケースの読み取り処理
通常のテキストファイルだけでなく、特殊な形式のファイル(空ファイル、改行のみのファイル、BOM付きファイルなど)も適切に処理できるように準備しておくことが、堅牢なアプリケーションには不可欠です。
空ファイルの処理
ファイルが空の場合、reader.result
は空文字列になります。この場合、特にエラーとせず、空のデータとして扱えば問題ありません。
reader.onload = (e) => {
const content = e.target.result;
if (content.length === 0) {
console.log('空のファイルが読み込まれました。');
// 必要に応じてユーザーに通知
document.getElementById('outputArea').textContent = 'ファイルは空です。';
} else {
// 通常の処理
document.getElementById('outputArea').textContent = content;
}
};
改行のみのファイルの処理
改行のみのファイルの場合、split('\n')
で分割すると空文字列の配列が生成されます。前述のfilter(line => line !== '')
を使うことで、不要な空行を除外できます。
BOM(Byte Order Mark)の削除
BOM付きUTF-8ファイルの処理は「文字化けはこれで解決!」のセクションで解説した通り、content.charCodeAt(0) === 0xFEFF
でチェックし、substring(1)
で削除することで対応できます。
これらの特殊ケースを考慮することで、より安定したファイル読み込み機能を提供できます。
特定の拡張子(.txt, .csvなど)のみファイル選択を制限する方法
ユーザーが誤って画像ファイルなどをテキストファイル読み込み機能にアップロードしてしまうのを防ぐため、ファイル選択ダイアログで許可するファイルの種類を制限できます。これは、<input type="file">
要素のaccept
属性を使用します。
<input type="file" id="specificFileInput" accept=".txt, .csv">
<input type="file" id="txtOnlyInput" accept="text/plain">
<input type="file" id="imageInput" accept="image/jpeg, image/png">
accept
属性には、以下のいずれかを指定します。
- ファイル拡張子:
.txt
,.csv
,.json
など、カンマ区切りで指定します。 - MIMEタイプ:
text/plain
,text/csv
,application/json
,image/jpeg
など、MIMEタイプを指定します。
accept
属性はあくまでヒントであり、ユーザーがファイルダイアログで「すべてのファイル」を選択すれば、指定外のファイルも選択できてしまいます。そのため、JavaScript側でもファイルの拡張子やMIMEタイプを検証することが推奨されます。
document.getElementById('specificFileInput').addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
// ファイル名から拡張子を取得
const fileName = file.name;
const fileExtension = fileName.split('.').pop().toLowerCase();
// MIMEタイプも確認
const fileMimeType = file.type;
// 許可する拡張子リスト
const allowedExtensions = ['txt', 'csv', 'json'];
// 許可するMIMEタイプリスト
const allowedMimeTypes = ['text/plain', 'text/csv', 'application/json'];
if (!allowedExtensions.includes(fileExtension) && !allowedMimeTypes.includes(fileMimeType)) {
alert('このファイルタイプは許可されていません。txt, csv, jsonファイルを選択してください。');
e.target.value = ''; // ファイル選択をクリア
return;
}
// ここからファイルの読み込み処理
// ...
}
});
accept
属性とJavaScriptによる二重チェックを行うことで、より堅牢なファイルタイプ検証を実現できます。
よくある質問(FAQ)
-
JavaScriptでサーバーのファイルを直接書き換えることはできますか?
-
いいえ、ブラウザのJavaScript(クライアントサイドJavaScript)から直接サーバー上のファイルを書き換えたり、削除したりすることはできません。これはセキュリティ上の理由で制限されています。サーバー上のファイルを操作するには、Node.jsなどのサーバーサイドJavaScriptやPHP、Pythonなどのサーバーサイド言語を使って、サーバー側のAPIを介して処理を行う必要があります。
-
ローカルのテキストファイルをJavaScriptで読み込む際、常にユーザーの操作が必要ですか?
-
基本的に、はい。ブラウザのセキュリティモデルにより、JavaScriptがユーザーの許可なくローカルファイルシステムにアクセスすることは禁じられています。そのため、input type=”file”要素によるファイル選択やドラッグ&ドロップなど、ユーザーの明示的な操作が必須となります。自動的に任意のローカルファイルを読み込むことはできません。
-
読み込み可能なテキストファイルのサイズに制限はありますか?
-
明確なサイズ制限はブラウザによって異なりますが、非常に大きなファイル(数十MB〜数GB)を読み込む場合、ブラウザのメモリを大量に消費し、動作が遅くなったり、フリーズしたりする可能性があります。大量のデータを扱う場合は、ファイルを分割して読み込むストリーム処理や、サーバーサイドでの処理を検討する必要があります。FileReaderはファイルをメモリにすべて読み込むため、特に注意が必要です。
-
モバイルデバイス(スマホやタブレット)でも、JavaScriptのファイル読み込み機能は動作しますか?
-
はい、現代のモバイルブラウザのほとんどはFileReader APIやfetch APIをサポートしており、PCと同様にJavaScriptでテキストファイルを読み込むことができます。input type=”file”もモバイルデバイスに対応しており、写真ライブラリからの選択や、ファイルアプリからの選択などが可能です。
まとめ
本記事では、JavaScriptでテキストファイルを読み込むための様々な方法を、具体的なコード例を交えて詳しく解説しました。
これであなたは、JavaScriptでテキストファイルを自在に操り、より高度でユーザーフレンドリーなWebアプリケーションを構築するための知識とスキルを手に入れました。ぜひ本記事のコード例を参考に、あなたのプロジェクトに役立ててください。

