𩸽という漢字はユニコードのサロゲートペアの代表例としてプログラマにはよく知られていますが、この漢字は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)