Java NIO2 UnmappableCharacterException

English follows Japanese.

  • 以下のようにファイルの出力をNIOからNIO2に書き換えた場合、出力時の値によっては動作が違ってきます。

「Pokémon」を文字コードsjisを指定してファイル出力する処理をNIOとNIO2で記述してみました。

  1. NIOの場合は、正常終了するのですが、出力したファイルは「Pock?mon」となっています。
  2. NIO2の場合は、UnmappableCharacterExceptionになります。

そもそも文字コードとして正しくない値を出力しているのが問題ではあるのですが、リファクタリングしたことで動作が違ってくるのは、、、

  • When you refactor codes from Java NIO to NIO2 like below, you will have different results.

I implemented the function which writes the value [Pokémon] to the file with sjis Charset.

  1. When using NIO the method ended without Exception, but the result is Pock?mon.
  2. When using NIO2 the method ended with UnmappableCharacterException.

Basically it is wrong using mismatched Charset, but I did not expect to see the different result... :-(

package com.sample;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Sample {
    public static void main(String... args) throws IOException {
        Sample sample = new Sample();
        sample.writeNIO();
        sample.writeNIO2();
    }

    void writeNIO() {
        String val = "Pockémon";
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream("/Users/tomo/NIO.txt"), Charset.forName("sjis")))) {
            writer.write(val);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    void writeNIO2() throws IOException {
        String val = "Pockémon";
        Path path = Paths.get("/Users", "tomo", "NIO2.txt");
        try (BufferedWriter writer = Files.newBufferedWriter(path, Charset.forName("sjis"));) {
            writer.write(val);
        }
    }
}
package com.sample;

import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.nio.charset.UnmappableCharacterException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.junit.Before;
import org.junit.Test;
public class SampleTest {
    Sample sample;

    @Before
    public void setUp() throws Exception {
        sample = new Sample();
    }
    @Test
    public void testWriteNIO() {
        sample.writeNIO();
        Path path = Paths.get("/Users", "tomo", "NIO.txt");
        boolean exists = Files.exists(path);
        assertTrue(exists);
    }

    @Test(expected = UnmappableCharacterException.class)
    public void testWriteNIO2() throws IOException {
        sample.writeNIO2();
    }

}

f:id:tomoTaka:20160730164258p:plain
The code is here gist.github.com