LoginSignup
3
0

More than 3 years have passed since last update.

対象の文字コードにない文字を書き込む際の挙動がFiles.writeとFiles.writeStringで異なる

Posted at

𩸽という漢字はユニコードのサロゲートペアの代表例としてプログラマにはよく知られていますが、この漢字はShift_JISには収録されていません。

Files.write(Paths.get("sjis.txt"), List.of("𩸽"), Charset.forName("SJIS"));

上のコードはFiles.writeを使って、この𩸽という漢字を文字コード=Shift_JISのファイルに書き込もうとするものですが、これを実行するとUnmappableCharacterExceptionが発生します。

Exception in thread "main" java.nio.charset.UnmappableCharacterException: Input length = 2
    at java.base/java.nio.charset.CoderResult.throwException(CoderResult.java:275)
    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.close(BufferedWriter.java:268)
    at java.base/java.nio.file.Files.write(Files.java:3493)
    at Iconv.main(Iconv.java:9)

さて、Java11で追加されたFiles.writeStringを使って同じことをしてみましょう。

Files.writeString(Paths.get("sjis.txt"), "𩸽", Charset.forName("SJIS"));

これを実行すると、同じようにUnmappableCharacterExceptionが発生するかと思いきや、例外は発生せず、処理は正常終了します。sjis.txtにも正常に書き込みされています。

もっとも𩸽という漢字が正しく書き込まれているわけではなく、文字コード=3F、すなわち?という文字に置換されてしまっているようです。

$ xxd sjis.txt
00000000: 3f                                       ?

環境情報:

C:\>javac -version
javac 11.0.3
C:\>java -version
openjdk version "11.0.3" 2019-04-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.3+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.3+7, mixed mode)
3
0
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
3
0