Javaのファイル読み込みは、BufferedReaderやFilesクラスなど選択肢が多く、どれを選べばいいか毎回迷う人は少なくありません。
実務で使うのは主に3つの基本パターンです。
ただし、CSVを扱うのか、数GB級のログを扱うのか、resourcesフォルダ配下の設定ファイルを読むのかによって、最適解は変わってきます。
BufferedReader・Files.readString・Files.lines・Scanner・getResourceAsStreamなど7つの実装パターンを、コピペで動くサンプルコード付きで整理しました。
CSV読み込み・大容量ファイル対応・文字コード指定・try-with-resourcesによるエラー処理まで扱っているので、目の前のファイルにどの方法を選べばいいか、この記事だけで判断できます。
Javaファイル読み込みの基本3つの方法
Javaのファイル読み込みとは、テキストファイルやCSV・プロパティファイルなどの中身を、プログラムから扱える形に変換する処理のことです。
具体的には、BufferedReaderやFilesクラスといった標準APIのクラスを経由します。

Javaでファイル読み込みを行うには、いくつかのクラスを組み合わせて使います。ここでは、最も基本的でよく使われる3つのアプローチを紹介します。
それぞれの特徴を理解して、状況に応じて使い分けられるようになりましょう。
Fileクラスを使った基本的な扱い方
まず基本となるのがjava.io.Fileクラスです。注意点として、Fileクラス自体にファイルを読み込む機能はありません。
Fileクラスは、ファイルやディレクトリのパスを抽象的に表現するためのものです。
ファイルが存在するかどうかを確認したり、ファイル名を取得したりする際に使います。ファイル操作の「窓口」と考えるとわかりやすいでしょう。
import java.io.File;
public class FileExample {
public static void main(String[] args) {
// ファイルのパスを指定してFileオブジェクトを作成
File file = new File("sample.txt");
// ファイルの存在確認
if (file.exists()) {
System.out.println("ファイルは存在します。");
// ファイルの絶対パスを取得
System.out.println("パス: " + file.getAbsolutePath());
// ファイル名を取得
System.out.println("ファイル名: " + file.getName());
} else {
System.out.println("ファイルが見つかりません。");
}
}
}このコードは、sample.txtというファイルが存在するかどうかをチェックするだけです。
実際の読み込みは、このFileオブジェクトを他のクラス(BufferedReaderなど)と組み合わせて行います。
BufferedReaderで1行ずつ読み込む
テキストファイルを1行ずつ読み込んで処理したい場合に最もよく使われるのがBufferedReaderクラスです。
BufferedReaderは、文字をバッファリングしながら読み込むため、効率的に処理できます。
readLine()メソッドを使うと、1行ずつ文字列として簡単に取得できるのが大きな特徴です。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderExample {
public static void main(String[] args) {
File file = new File("sample.txt");
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
// 1行ずつ読み込み、行がなくなるまでループ
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}この例ではFileReaderと組み合わせています。
FileReaderがファイルから文字を読み込み、それをBufferedReaderが効率化して1行ずつ提供するイメージです。
大量の行があるファイルを扱う場合に非常に有効なファイル読み込みの方法です。
私自身、業務で数十万行のアクセスログを解析するバッチ処理を書いた際に、BufferedReaderの安定性に助けられました。
メモリ消費が一定のまま処理が進むので、本番環境でも安心して使えます。
Scannerを使った簡単な入力処理
Scannerクラスは、コンソールからの入力受付によく使われますが、ファイルの読み込みにも利用できます。
Scannerの便利な点は、スペースや改行などの区切り文字を指定して、単語ごとにデータを読み込めることです。
また、nextInt()やnextDouble()といったメソッドを使えば、数値を直接読み取れるため、データ処理が簡単になります。
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
File file = new File("sample.txt");
try (Scanner scanner = new Scanner(file)) {
// ファイルの最後まで単語ごとに読み込む
while (scanner.hasNext()) {
String word = scanner.next();
System.out.println(word);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}簡単なテキストデータや、スペース区切りのデータを手軽に扱いたい場合にはScannerが便利です。
ファイル読み込み方法の比較と使い分け

ここまで紹介した基本的な方法には、それぞれ得意なことと不得意なことがあります。ここでは、それぞれの違いや、よりモダンな書き方について見ていきましょう。
BufferedReaderとScannerの違い
BufferedReaderとScannerはどちらもよく使われるため、どちらを選ぶべきか迷うかもしれません。主な違いはパフォーマンスと機能性です。
| 項目 | BufferedReader | Scanner |
| 主な目的 | 1行ずつの高速な読み込み | 区切り文字を使った解析的な読み込み |
| パフォーマンス | 高速。バッファリングにより効率が良い。 | 比較的低速。正規表現による解析処理のため。 |
| 機能性 | readLine()による行単位の読み込みが基本。 | next(), nextInt()などデータ型に合わせた多彩な読み込みが可能。 |
| スレッドセーフ | スレッドセーフ | スレッドセーフではない |
単純にテキストファイルを1行ずつ読み込みたいだけならBufferedReader、スペース区切りのデータや数値を直接扱いたいならScannerを選ぶと良いでしょう。
パフォーマンスが重要視される大規模なデータ処理では、BufferedReaderの使用が推奨されます。
Filesクラス(Java 7以降)の活用
Java 7で導入されたNIO.2(New I/O 2)のFilesクラスを使うと、ファイル読み込みをさらに簡潔に記述できます。
2026年現在の最新LTSはJava 25(2025年9月リリース)です。
Java 21も含め幅広いLTSバージョンで引き続き推奨されるAPIのため、これから学ぶならこの方法を最優先で覚えましょう。
これまでのBufferedReaderなどを使った書き方よりも、はるかに少ないコード量で済むのが最大のメリットです。
例えば、ファイルの内容をすべて一度に読み込んで文字列にする場合、Files.readString()を使えばたった1行です。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FilesExample {
public static void main(String[] args) {
Path path = Paths.get("sample.txt");
try {
// ファイルの全行をリストとして読み込む (Java 8+)
// List<String> lines = Files.readAllLines(path);
// System.out.println(lines);
// ファイルの全内容を1つの文字列として読み込む (Java 11+)
String content = Files.readString(path);
System.out.println(content);
} catch (IOException e) {
e.printStackTrace();
}
}
}小さな設定ファイルなどを読み込む際には、このFilesクラスを使う方法が最も手軽で間違いがありません。
ただし、巨大なファイルを一括で読み込むとメモリを大量に消費するため、注意が必要です。
文字コード(エンコーディング)への注意点
Windowsで作成したテキストファイルをMacやLinuxで開くと、文字化けすることがあります。
同じように、Javaのファイル読み込みでも文字コードは非常に重要な問題です。
Java 17以前では、特に指定しない場合、OSのデフォルト文字コードが使われていました。
しかしJava 18以降、デフォルト文字コードはOSに関係なくUTF-8に統一されています。
Java 17以前の環境やShift_JISファイルを扱う場合は、明示的に文字コードを指定する必要があります。
私の経験では、文字コード問題は「開発環境では正常に動くが本番で文字化けする」という形で発覚するケースが大半です。
開発端末がMac(UTF-8)で本番がWindows Server(Shift_JIS)だった場合に頻発します。
読み込むファイルの文字コードが分かっている場合は、必ず明示的に指定しましょう。
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class CharsetExample {
public static void main(String[] args) {
// Shift_JISでエンコードされたファイルを読み込む例
try (BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream("sample_sjis.txt"), StandardCharsets.UTF_8))) { // ここではUTF-8を指定
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}InputStreamReaderを使うと、FileInputStreamで読み込んだバイトデータを、指定した文字コードで文字に変換できます。
2026年現在、新規プロジェクトではUTF-8が事実上の標準です。
ただし、官公庁系システムや銀行系レガシーではShift_JISが残っていることもあるため、この方法は覚えておくと役立ちます。
実践的なファイル読み込みサンプルコード

ここからは、より具体的なシナリオを想定したファイル読み込みサンプルコードを見ていきます。
テキストファイルを一括で読み込む
設定ファイルなど、数KB程度の小さなファイルであれば、中身を一度にすべてメモリに読み込んでしまうのが最も簡単です。
前述のFiles.readString()が最適です。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class ReadAllText {
public static void main(String[] args) {
Path path = Path.of("config.txt");
try {
String configContent = Files.readString(path);
System.out.println("--- 設定ファイルの内容 ---");
System.out.println(configContent);
} catch (IOException e) {
System.err.println("ファイルの読み込みに失敗しました: " + e.getMessage());
}
}
}この方法なら、面倒なループ処理やリソースのクローズ処理を気にする必要がありません。
CSVファイルを読み込んで処理する|split()とOpenCSVの使い分け
カンマ区切りのCSVファイルは、データ交換のフォーマットとして頻繁に使われます。
BufferedReaderで1行ずつ読み込み、Stringクラスのsplit()メソッドでカンマを基準に分割するのが基本的な処理方法です。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CsvReader {
public static void main(String[] args) {
String csvFile = "users.csv";
String line;
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
// ヘッダー行を読み飛ばす場合
// br.readLine();
while ((line = br.readLine()) != null) {
String[] user = line.split(",");
System.out.println("ID: " + user[0] + ", 名前: " + user[1] + ", メール: " + user[2]);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
users.csvファイルを1行ずつ読み込み、各行をカンマで分割してユーザー情報を表示します。
本格的なCSV処理では、データ内にカンマが含まれるケースなどを考慮する必要があります。
そのため、OpenCSVやApache Commons CSVなどのライブラリを使うのが一般的です。
ただし、簡単なものであればこの方法でも対応できます。
実務では、CSVファイルのデータ内にカンマやダブルクォートが含まれるケースが想像以上に多いです。
特に顧客名や住所フィールドで問題が発生しやすいため、本番データを扱うなら早い段階でライブラリの導入を検討してください。
目安として、扱う行数が数百行を超えたあたりで自前パースを諦め、OpenCSV等に切り替えるのがおすすめです。
後々のカンマ・改行混入バグへの対応コストを考えると、結果的に安く済みます。
OpenCSVライブラリでCSVを読み込む
OpenCSVは、引用符付きフィールド内のカンマや改行を正しく解釈できる専用ライブラリです。
Maven/Gradleに依存関係を追加するだけで使えます。
<!-- pom.xml -->
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.12.0</version>
</dependency>import com.opencsv.CSVReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
public class CsvReaderOpenCSV {
public static void main(String[] args) throws IOException {
String path = "users.csv";
try (CSVReader reader = new CSVReader(new FileReader(path))) {
List<String[]> lines = reader.readAll();
for (String[] line : lines) {
System.out.println("ID: " + line[0] + ", 名前: " + line[1] + ", メール: " + line[2]);
}
} catch (com.opencsv.exceptions.CsvException e) {
e.printStackTrace();
}
}
}reader.readAll()を使えば、カンマや改行が値の中に含まれていても正しく行単位・列単位に分割してくれます。
自前のsplit(",")は手軽な反面、値の中にカンマが1つでも混入すると壊れます。
本番データのCSVを扱うなら、最初からOpenCSVを選ぶ方が結果的にトラブルが少なくなります。
大容量ファイルを効率的に扱う
数GBにもなるような大容量のログファイルなどを扱う場合、ファイル全体をメモリに読み込むのは現実的ではありません。
OutOfMemoryErrorという致命的なエラーが発生してしまいます。
「まとめて読み込んだ方が効率的なはず」という直感は、データ量が増えるほど裏切られます。
以前、Spring Batchのバッチ処理でchunk sizeを1000件に設定していたところ、本番環境がOutOfMemoryErrorで落ちたことがありました。
原因調査に2時間かかった一方、修正はchunk sizeを100件に下げるだけの5分で完了しました。ファイル読み込みでも構造は同じです。
Files.readAllLines()で「とりあえず全部読む」実装は、開発環境の小さなテストデータでは問題が表面化しません。
本番の大容量ファイルで、初めて牙を剥きます。
このようなケースでは、ストリーム処理が必須です。ストリーム処理とは、データを少しずつ読み込みながら処理を進める方式です。
BufferedReaderのreadLine()ループや、Java 8から導入されたFiles.lines()メソッドがこれにあたります。
2026年現在の最新LTSであるJava 25でも変わらず推奨される書き方です。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
public class LargeFileReader {
public static void main(String[] args) {
Path path = Path.of("large_log_file.log");
// try-with-resourcesでStreamを自動的にクローズする
try (Stream<String> lines = Files.lines(path)) {
// "ERROR"という単語を含む行だけをカウントする
long errorCount = lines.filter(line -> line.contains("ERROR")).count();
System.out.println("エラー行数: " + errorCount);
} catch (IOException e) {
e.printStackTrace();
}
}
}Files.lines()は、ファイルを行ストリームとして扱えるようにします。
メモリ消費を最小限に抑えながら、フィルタリングや集計といった高度なデータ処理を簡潔に記述できるのです。
大容量ファイルを扱う際のファイル読み込みでは、この方法が現在のベストプラクティスです。
resourcesフォルダのファイル読み込み(クラスパス)
Mavenや Gradleプロジェクトでは、設定ファイルやテンプレートをsrc/main/resourcesに配置するのが一般的です。
このresourcesフォルダ内のファイルは、Fileクラスで直接パスを指定しても読み込めません。
代わりにgetResourceAsStream()を使います。
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
public class ResourceReader {
public static void main(String[] args) {
// クラスパス上の "config.properties" を読み込む
try (InputStream is = ResourceReader.class.getResourceAsStream("/config.properties");
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException | NullPointerException e) {
System.err.println("リソースの読み込みに失敗しました: " + e.getMessage());
}
}
}パスの先頭に/を付けるとクラスパスのルートからの絶対パスになります。/なしだと呼び出し元クラスのパッケージからの相対パスです。
getResourceAsStream()は見つからない場合にnullを返すため、NullPointerExceptionへの対策も忘れずに入れておきましょう。
JARファイルにパッケージした後も、この方法なら正しくリソースを読み込めます。
そのため、プロジェクト内の設定ファイルやテンプレートにはgetResourceAsStream()を使うのが鉄則です。
プロパティファイルを読み込む(Propertiesクラス)
設定値をキーとバリューのペアで管理したい場合は、java.util.Propertiesクラスが便利です。
.properties形式のファイルをload()メソッドに渡すだけで、シンプルな設定管理が実現できます。
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesExample {
public static void main(String[] args) {
Properties props = new Properties();
// クラスパス上の config.properties を読み込む
try (InputStream is = PropertiesExample.class.getResourceAsStream("/config.properties")) {
props.load(is);
String dbUrl = props.getProperty("db.url");
System.out.println("db.url = " + dbUrl);
} catch (IOException e) {
System.err.println("プロパティファイルの読み込みに失敗しました: " + e.getMessage());
}
}
}前述のgetResourceAsStream()と組み合わせれば、JARファイルにパッケージされた設定ファイルもそのまま読み込めます。
DB接続情報やAPIキーなど、環境ごとに差し替えたい値を管理する用途でよく使われる方法です。
ここで注意したいのが文字コードです。
Properties#load(InputStream)は、内部でISO-8859-1(Latin-1)としてバイト列を解釈します。
そのため、日本語のコメントや値を含む.propertiesファイルを上記のコードでそのまま読み込むと文字化けします。
日本語を扱う場合は、load(InputStream)ではなくload(Reader)を使い、InputStreamReaderでUTF-8を明示的に指定してください。
JSONファイルを読み込む
JavaにはJSONを解析する標準APIが含まれていないため、JacksonやGsonといった外部ライブラリを使うのが一般的です。
ここでは広く使われているJacksonの例を紹介します。
2025年10月にはgroupIdがtools.jackson.coreに変わるJackson 3.0もGAリリースされていますが、既存プロジェクトの多くはまだ2.x系を使っているため、ここでは安定した2.x系の書き方を紹介します。
// build.gradle: implementation 'com.fasterxml.jackson.core:jackson-databind:2.22.2'
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
public class JsonExample {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
try {
User user = mapper.readValue(new File("user.json"), User.class);
System.out.println(user.getName());
} catch (IOException e) {
System.err.println("JSONの読み込みに失敗しました: " + e.getMessage());
}
}
}readValue()にJSONファイルとマッピング先のクラスを渡すだけで、フィールド名が一致していれば自動的にオブジェクトへ変換してくれます。
Files.readString()で文字列として読み込んでから自前でパースすることも、技術的には可能です。
ただし、ネストしたJSONの扱いが煩雑になるため、実務ではライブラリを使う方法が推奨されます。
ファイル読み込み時のエラー処理

ファイル操作にはエラーがつきものです。ファイルが存在しなかったり、読み込み権限がなかったりと、予期せぬ事態は常に起こり得ます。
堅牢なプログラムを作るためには、適切なエラー処理が不可欠です。
FileNotFoundExceptionへの対応
FileNotFoundExceptionは、その名の通り「指定されたパスにファイルが見つからない」場合に発生する、最も代表的な例外です。
FileNotFoundExceptionが発生するということは、プログラムの前提が崩れている状態です。
ユーザーにファイルパスを再入力させたり、処理を中断してエラーメッセージを表示したりといった対応が必要です。
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileNotFoundHandler {
public static void main(String[] args) {
File file = new File("non_existent_file.txt");
try {
Scanner scanner = new Scanner(file);
// ... 読み込み処理 ...
} catch (FileNotFoundException e) {
System.err.println("エラー: ファイルが見つかりません。");
System.err.println("パスを確認してください: " + file.getAbsolutePath());
}
}
}catchブロックでこの例外を捕まえ、利用者に分かりやすいメッセージを出すことが重要です。
IOExceptionの基本的なハンドリング
IOExceptionは、I/O操作全般で発生する可能性のある、より広範な例外です。
FileNotFoundExceptionもIOExceptionの一種です。
ディスクの故障やネットワークの切断で読み込みが中断された場合にもIOExceptionが発生します。
ファイル操作を行うコードは、必ずIOExceptionを処理するtry-catchブロックで囲んでください。
try-with-resourcesを使った安全な書き方
Java 7から導入されたtry-with-resources文は、ファイル読み込みにおけるエラー処理とリソース管理を劇的に改善しました。
古いコードでは、finallyブロックでclose()メソッドを呼び出し、リソースを明示的に閉じる必要がありました。
このclose()処理を忘れると、ファイルハンドルが解放されずに残り、システムの不安定化を招く原因となります。
try-with-resourcesを使えば、tryブロックを抜ける際に自動的にリソースをクローズしてくれます。
// 悪い例(Java 6以前の古い書き方)
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("sample.txt"));
// ... 読み込み処理 ...
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close(); // 手動でクローズする必要がある
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 良い例(Java 7以降のモダンな書き方)
try (BufferedReader br = new BufferedReader(new FileReader("sample.txt"))) {
// ... 読み込み処理 ...
// tryブロックを抜ける際に自動でbr.close()が呼ばれる
} catch (IOException e) {
e.printStackTrace();
}コードがシンプルになるだけでなく、close()の呼び忘れも防げるため、現在のJavaではtry-with-resources文を使うのが常識です。
特別な理由がない限り、必ずこの書き方を採用してください。
実際のコードレビューでも、try-with-resourcesを使っていないコードは即座に指摘対象になります。
レガシーコードのリファクタリング案件でも、最初に手をつけるべき改善箇所です。
よくある質問(FAQ)
Javaでファイルを読み込む最も簡単な方法は?
Java 11以降であればFiles.readString(Path)が最も簡単です。1行で全内容を文字列として取得できます。ただし、ファイルサイズが大きい場合はメモリを圧迫するため、数KB〜数MB程度の設定ファイルや小さなテキストファイル向けです。
BufferedReaderとScannerはどちらを使うべき?
テキストファイルを1行ずつ処理するならBufferedReaderが高速で推奨です。スペース区切りのデータや数値を直接読み取りたい場合はScannerが便利です。パフォーマンスが重要な大規模処理ではBufferedReader一択です。
大容量ファイルを読み込むとOutOfMemoryErrorが出るのはなぜ?
Files.readAllLines()やFiles.readString()は、ファイル全体をメモリに展開します。そのため、数GB規模のファイルではヒープ領域が不足します。Files.lines()やBufferedReaderのループで1行ずつ処理するストリーム方式に切り替えてください。
resourcesフォルダ内のファイルを読み込むにはどうすればいい?
Fileクラスで直接パスを指定しても読み込めません。getResourceAsStream()を使い、クラスパス経由でInputStreamとして取得してください。JARファイルにパッケージした後も同じ方法で読み込めます。
プロパティファイルの日本語が文字化けするのはなぜ?
Properties#load(InputStream)が内部でISO-8859-1(Latin-1)としてバイト列を解釈するためです。日本語を含む場合はload(Reader)にUTF-8指定のInputStreamReaderを渡してください。
JSONファイルを読み込むのに標準APIだけで足りる?
いいえ、足りません。JavaにはJSON解析の標準APIが含まれていないため、JacksonやGsonなどの外部ライブラリを使うのが一般的です。Files.readString()で読み込んで自前パースすることも技術的には可能ですが、ネストしたJSONでは煩雑になります。
文字コードを指定せずにファイルを読み込むとどうなる?
Java 18以降はOSに関係なくデフォルトでUTF-8として読み込まれます。ただしShift_JIS等のファイルを扱う場合や、Java 17以前の環境では文字化けするため、StandardCharsetsで明示的に文字コードを指定してください。
まとめ
今回は、Javaにおけるファイル読み込みの基本から実践的なテクニック、そして重要なエラー処理までを解説しました。
最後に、ポイントを振り返ってみましょう。
目的別に使い分ける読み込み方法
- 小さなファイルを一括で読みたい ->
Files.readString()やFiles.readAllLines()が手軽で最適。 - ファイルを1行ずつ処理したい ->
BufferedReaderを使うのが基本。パフォーマンスも良い。 - 大容量ファイルを効率的に扱いたい ->
Files.lines()を使ったストリーム処理が必須。メモリを圧迫しない。 - スペース区切りなど簡単なデータを解析したい ->
Scannerが便利。 - クラスパス上のリソースを読みたい ->
getResourceAsStream()を使えばJAR内でも動作する。
※本記事のバージョン情報は2026年9月時点のものです(Java 25 LTS・OpenCSV 5.12.0・Jackson 2.22.2基準)。ライブラリのバージョンは適宜最新のものをご確認ください。








