JavaでShift_JIS変換時に文字化けする原因と対処法(MS932対応)

先日、Oracleから取得した文字列を Shift_JIS に変換したところ、外字だけ文字化けしました。 調べてみると、いわゆる「Shift_JIS」運用でも、実際は MS932(Windows-31J)前提のケースがあるとわかったので、備忘録として残します。

忙しい人向け

Shift_JIS で変換できない文字を含んでいたのが原因でした。 Java側で文字コード指定を Shift_JIS から MS932 に変更したら解消しました。

問題発生時のファイル構成(例)

sample-project/
└─ src/main/java/com/example/charset/Main.java

発生環境

  • Java: 11
  • DB: Oracle
  • 事象: Oracleから取得した文字列をCSV向けにShift_JIS変換すると、一部文字が ? になる

症状

今回の再現文字列は ㈱あいティーブログ です。 ㈱ が Shift_JIS では変換できず、? に置換されました。

import java.nio.charset.Charset;

public class Main {
    public static void main(String[] args) {
        String sample = "㈱あいティーブログ";

        Charset sjis = Charset.forName("Shift_JIS");
        Charset ms932 = Charset.forName("MS932");

        System.out.println(new String(sample.getBytes(sjis), sjis));
        System.out.println(new String(sample.getBytes(ms932), ms932));
    }
}

実行結果(例)

?あいティーブログ
㈱あいティーブログ

前提条件

  • Java 11 以降(対処手順で Files.writeString を使うため)
  • 連携先の仕様は「Shift_JIS」だが、実際は Windows 系で MS932(Windows-31J)を想定している
  • データに ㈱ などの機種依存文字(NEC特殊文字など)が含まれる

原因

  1. Shift_JIS と MS932 は同じではなく、文字集合に差がある
  2. Shift_JIS で表現できない文字は、変換時に ? へ置換される
  3. 連携先が「Shift_JIS」と書いていても、実装としては MS932 前提のことがある

対処手順

変換時の指定文字コードを MS932 に変更します。

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;

String body = "会社名\n㈱あいティーブログ";
Charset charset = Charset.forName("MS932");
Files.writeString(Path.of("output.csv"), body, charset);

必要であれば、CharsetEncoder で CodingErrorAction.REPORT を指定し、変換不能文字を例外として検知すると運用しやすくなります。

まとめ

Javaで日本語ファイル連携をするときは、「Shift_JIS」という表記だけを鵜呑みにしないのが大事でした。 文字化けが起きたら、まず MS932 指定での再現確認をしてみるのが早いです。

参考リンク