1
1

More than 3 years have passed since last update.

書くときにも発生する MalformedInputException

Posted at

自分が書いた Java プログラムが以下のエラーを出力した。

Caused by: java.nio.charset.MalformedInputException: Input length = 1
    at java.base/java.nio.charset.CoderResult.throwException(CoderResult.java:274)
    at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:306)
    at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:281)
    at java.base/sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)
    at java.base/java.io.OutputStreamWriter.write(OutputStreamWriter.java:211)
    at java.base/java.io.BufferedWriter.flushBuffer(BufferedWriter.java:120)
    at java.base/java.io.BufferedWriter.flush(BufferedWriter.java:256)
以下アプリケーションコードのスタックトレース部分を省略

文字エンコーディングに関する問題であることはすぐわかるが、次のアプリケーションコードの該当箇所を見ても理由が思い当たらない。

File file = ...;
try (BufferedWriter writer = java.nio.file.Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
    String s = ...;
    writer.write(s);
    writer.flush(); // ここでエラーが出るので直前の write の引数が怪しいが...
}

こういうときは文字列の s をダンプして s の中身を調べるのが常套手段。

System.err.println("[" + s + "]");

とすると、以下のように表示された。? は何だろう、文字化けか?
そもそも、System.err#println だとエラーが出ないのか...

[?]

ここで サロゲートペア にすぐ気づかなかったのは迂闊であった。
以下のコードで s の各文字を調べると、 High. が表示された。最初のエラーの原因はこれだ。

for (char c : s.toCharArray()) {
    if (Character.isHighSurrogate(c)) {
        System.err.println("High.");
    }
    if (Character.isLowSurrogate(c)) {
        System.err.println("Low.");
    }
}

2020年現在、サロゲートペアをきちんと考慮した Java プログラミングは、常識のお作法であろうか。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1