- JAVA
MalformedInputExceptionの直し方|Java文字コード
java.nio.charset.MalformedInputException: Input length = 1 は、ファイルを UTF-8 として読もうとしたが、UTF-8 として正しくないバイトがあったときの例外です。 日本では、Excel などで作った Shift_JIS(windows-31j)の CSV を、Files.readAllLines などで読んだときによく起きます。
List<String> lines = Files.readAllLines(Path.of("sjis.csv")); // 文字コードを指定していない → UTF-8 で読む
Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1
at java.base/java.nio.charset.CoderResult.throwException(CoderResult.java:279)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:405)
...
直し方は、ファイルの本当の文字コードを指定して読むことです。
List<String> lines = Files.readAllLines(Path.of("sjis.csv"), Charset.forName("windows-31j"));
| ファイルの文字コード | 指定する Charset |
|---|---|
| UTF-8(BOM なし) | StandardCharsets.UTF_8(Files の既定) |
| Excel などの Shift_JIS | Charset.forName("windows-31j")(MS932 と同じ) |
| UTF-8(BOM 付き) | UTF-8 で読み、先頭の BOM()を取り除く |
Input length = 1 は「1バイトの読めない並びがあった」という意味で、ファイルの長さとは関係ありません。
確認環境:OpenJDK 11・17・21・25(Linux)。山田・髙橋① を含む CSV を cp932 で保存して再現しました(確認日 2026年10月11日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MalformedInputExceptionの直し方|Java文字コード」
例外になる読み方と、黙って文字化けする読み方
Shift_JIS の CSV(1,山田 など)を、文字コードを指定せずにいろいろな方法で読みました(JDK 21)。
| 読み方 | 結果 |
|---|---|
Files.readAllLines(p) |
MalformedInputException |
Files.readString(p) |
MalformedInputException |
Files.newBufferedReader(p).readLine() |
MalformedInputException(1行目から) |
Files.lines(p).count() |
UncheckedIOException(中身は MalformedInputException) |
new FileReader(file) |
例外なし。1,�R�c と文字化け |
new Scanner(p) |
例外なし。1,�R�c と文字化け |
new String(bytes, UTF_8) |
例外なし。1,�R�c と文字化け |
Files のメソッドは、読めないバイトがあると例外にしました。FileReader・Scanner・new String は、読めないバイトを �(U+FFFD)に置き換えて、そのまま続けました。 例外が出るほうが、気づけるだけ安全です。FileReader で読んでいるプログラムは、データが化けたまま DB に入っていないかを確かめます。
Java の公式ドキュメントでは、Files.readString は UTF-8 でバイトを文字に変えると説明されています。 確認環境では、readAllLines・newBufferedReader・lines も、文字コードを指定しないと UTF-8 で読みました。
Files.lines は UncheckedIOException になる
java.io.UncheckedIOException: java.nio.charset.MalformedInputException: Input length = 1
Stream の中で起きるため、UncheckedIOException に包まれていました。 catch (IOException e) では捕まえられないので、ログに出る例外の名前が違っても、原因は同じです。
windows-31j と Shift_JIS の違い
| 指定した Charset | 1,山田 |
2,髙橋① |
|---|---|---|
windows-31j |
読めた | 読めた |
Shift_JIS |
読めた | MalformedInputException |
Shift_JIS を指定すると、はしごだか(髙)や丸数字(①)のような Windows の文字で例外になりました。 Windows・Excel で作ったファイルは、windows-31j(別名 MS932)を指定します。
逆に、UTF-8 のファイルを windows-31j で読むと
| 読み方 | 結果 |
|---|---|
UTF-8 の 1,山田 を windows-31j で読む |
例外なし。1,螻ア逕ー と文字化け |
windows-31j で読むと、例外にならずに化けることがありました。 「とりあえず windows-31j」で読まず、ファイルの文字コードを確かめてから指定します。
UTF-8 の BOM 付きファイル
先頭の行の長さ = 8、先頭の文字のコード = 65279(U+FEFF)
BOM 付きの UTF-8 は例外になりませんが、1行目の先頭に が残りました(id,name は7文字なのに、長さが8)。1列目の列名が一致しない原因になるので、読み込んだあとに取り除きます。
String first = lines.get(0);
if (!first.isEmpty() && first.charAt(0) == '') lines.set(0, first.substring(1));
CSV の文字コードの扱いは、既存の記事「Java CSV読み込み・書き込み入門|文字化けを防ぐBOMと文字コード」で扱っています。
どの行が読めないかを探す
byte[] all = Files.readAllBytes(Path.of("sjis.csv"));
int line = 1, start = 0;
for (int i = 0; i <= all.length; i++) {
if (i == all.length || all[i] == '\n') {
var dec = StandardCharsets.UTF_8.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
try {
dec.decode(ByteBuffer.wrap(all, start, i - start));
} catch (CharacterCodingException e) {
System.out.println("UTF-8 で読めない行: " + line);
}
line++; start = i + 1;
}
}
UTF-8 で読めない行: 2
UTF-8 で読めない行: 3
「ほとんど UTF-8 だが、一部の行だけ Shift_JIS が混ざっている」ファイル(複数の取引先のデータをつないだものなど)は、この方法で行を特定できます。1行目(id,name)は英数字だけなので、どちらの文字コードでも読めました。
JDK 18 以降で、FileReader の動きが変わる
JEP 400 により、JDK 18 から既定の文字コードは UTF-8 です。 以前の版の JDK を日本語の Windows で使っていたときは、FileReader は windows-31j で読んでいた可能性があります。JDK を上げたら、Shift_JIS の CSV が化け始めたという場合は、この変更が原因です。JEP 400 では、文字コードをコードで明示するか、ファイルを UTF-8 にそろえるまでの間 -Dfile.encoding=COMPAT で起動する方法が挙げられています。
| 直し方 | 内容 |
|---|---|
| コードで文字コードを明示する(おすすめ) | new FileReader(file, Charset.forName("windows-31j"))、Files.readAllLines(p, cs) |
| 起動オプションで以前の動きに戻す | -Dfile.encoding=COMPAT(JEP 400)。Files のメソッドには効かない |
確認環境で -Dfile.encoding=COMPAT を付けても、Files.readAllLines(p) は MalformedInputException のままでした。 Files は既定の文字コードではなく UTF-8 で読むためです。
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | ファイルの文字コード | エディタの表示、file -i(確認環境の Shift_JIS は unknown-8bit と表示) |
| 2 | 読み方 | Files(例外)か FileReader(文字化け)か |
| 3 | Charset の指定 | Windows・Excel のファイルは windows-31j |
| 4 | 一部の行だけか | 読めない行を探すコード |
| 5 | BOM | 1行目の |
よくある質問
Q. コンパイルのときの文字コードのエラーとは違いますか。
A. 違います。javac の unmappable character for encoding は、ソースファイルの文字コードの問題です。関連記事の「unmappable characterの直し方|javacの文字コード」で扱っています。
まとめ
- UTF-8 として正しくないバイトを、UTF-8 で読もうとした例外
Files.readAllLines(p)は UTF-8 で読む。Shift_JIS の CSV はwindows-31jを指定FileReader・Scannerは例外にならず、�に化けるShift_JISでは 髙・① が読めない。Windows のファイルはwindows-31j- JDK 18 から既定が UTF-8(JEP 400)。
-Dfile.encoding=COMPATはFilesには効かない
参考・出典
確認日はいずれも 2026年10月11日です。
- Java SE 21 API「Files」(readString は UTF-8 で読む):https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/nio/file/Files.html
- JEP 400「UTF-8 by Default」:https://openjdk.org/jeps/400
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MalformedInputExceptionの直し方|Java文字コード」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。