S-JIS[2022-03-23] 変更履歴

キャラクターセット(Charset)

Charsetは、Javaでエンコードを扱うクラス。


概要

キャラクターセット(java.nio.charset.Charset)は、 文字コードの種類(エンコード)を管理するクラス。[2007-02-13]
エンコードとは、例えばShift_JIS・MS932とかUTF-8とか。→エンコードの表記方法の他言語との比較

JavaのStringは内部ではUnicodeで文字列を保持しているので、例えばファイルにShift_JIS(SJIS)で出力したいときは、SJISのキャラセットをWriterに指定する。
バイト配列に特定エンコードの文字コード列を出力したいときは、String#getBytes()にキャラセットを指定する。

キャラセット名は、正式な名称の他にエイリアスが用意されている。
例えば「MS932」はエイリアスで、正式名は「windows-31j」。「SJIS」はエイリアスで、「Shift_JIS」が正式名。


デフォルトのキャラセット

Java18でデフォルトのキャラセットはUTF-8になった。[2022-03-23]
Java18より前は、デフォルトのキャラセットは実行環境依存だった。(例えばWindowsだとMS932)

現在のデフォルトのキャラセットはCharset.defaultCharset()で取得できる。

デフォルトのキャラセットを変更するには、システムプロパティーfile.encodingを指定する。

> java -Dfile.encoding=UTF-8
システムプロパティー 説明
file.encoding 主にファイル入出力用(ReaderWriter)のエンコーディング。
Java18より前は環境依存の値が返る。(例えばWindowsだとMS932)
Java18以降は特に指定が無い場合はUTF-8。
(Java18以降で)javaコマンドに-Dfile.encoding=COMPATを指定すると、環境依存の値になる。
(COMPATはcompatibility(互換性)のことかな?)
native.encoding 環境依存のエンコーディング。Java17以降。
Java17では、file.encodingと同じ値。

WindowsのJava18の例:

public class Encoding {
    public static void main(String... args) {
        System.out.println("file.encoding  =" + System.getProperty("file.encoding"));
        System.out.println("native.encoding=" + System.getProperty("native.encoding"));
    }
}
> java Encoding
file.encoding  =UTF-8
native.encoding=MS932

> java -Dfile.encoding=COMPAT Encoding
file.encoding  =MS932
native.encoding=MS932

Charset

Charsetの使用例。[2007-02-13]

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
Charset関連よく使うメソッド
内容備考
デフォルトのキャラセットCharset cs = Charset.defaultCharset();JDK1.5から使用可能。
システムプロパティーの「file.encoding」で指定された内容。
キャラセットの名前String name = cs.name(); 
特定名称のキャラセットCharset cs = Charset.forName("MS932");大文字でも小文字でも取得可能。
特定のキャラセットCharset cs = StandardCharsets.UTF_8;よく使うキャラセット(JDK1.7)[2013-12-20]
利用可能な名前Map m = Charset.availableCharsets();
Set s = cs.aliases();
 
デコーダー
エンコーダー
CharsetDecoder decoder = cs.newDecoder();
CharsetEncoder encoder = cs.newEncoder();
CharsetDecoderの使用例 [2009-01-16]

利用可能な名称・エイリアス一覧:

import java.nio.charset.Charset;
	public static void printCharsets() {	// keySet()を使用した例(JDK1.4形式)

		// 使用可能なキャラセット
		SortedMap m = Charset.availableCharsets();
		for (Iterator i = m.keySet().iterator(); i.hasNext();) {
			String name = (String) i.next();
			System.out.println(name);

			// エイリアス
			Charset c = Charset.forName(name);
			for (Iterator j = c.aliases().iterator(); j.hasNext();) {
				String alias = (String) j.next();
				System.out.println(" " + alias);
			}
		}
	}
	public static void printCharsets() {	// values()を使用した例(JDK1.5形式)

		// 使用可能なキャラセット
		SortedMap<String, Charset> m = Charset.availableCharsets();
			for (Charset c : m.values()) {
			System.out.println(c.name());

			// エイリアス
			for (String alias : c.aliases()) {
				System.out.println(" " + alias);
			}
		}
	}
Big5
 csBig5
〜
EUC-JP
 eucjis
 x-eucjp
〜
ISO-2022-JP
 jis
〜
Shift_JIS
 shift-jis
 x-sjis
 ms_kanji
 shift_jis
 csShiftJIS







 sjis
 pck
TIS-620
US-ASCII
 ISO646-US
 IBM367
 ASCII
 cp367
 default		←デフォルトはASCIIか!やっぱり(苦笑) file.encodingが「default」だと、これが使われる模様windows-31j
 csWindows31J
 windows-932







 MS932

SJISとMS932の違い

SJIS(Shift_JIS)もMS932(Windows-31J)も どちらも似たようなキャラセットだが、いわゆる機種依存文字が対応しているかどうか(Unicodeと変換できるかどうか)が異なる。[2007-02-13]

	String str = "あいうえおー−括@";

	byte[] m932 = str.getBytes("MS932");
	System.out.println("MS932:" + new String(m932, "MS932"));

	byte[] sjis = str.getBytes("SJIS");
	System.out.println("SJIS :" + new String(sjis, "SJIS"));
MS932:あいうえおー−括@
SJIS :あいうえおー???	←Shift_JISは、機種依存文字や全角ハイフンが文字化けする

なお、「?」への変換(文字化け)は、String#getBytes("SJIS")によって文字列からバイト配列へ変換(UNICODEからSJISへ変換)する際に行われる。[2009-02-14]
(コンソールへの出力の際に化けているわけではない)

	for (int i = 0; i < m932.length; i++) {
		System.out.printf(" %02x", m932[i]);
	}
	System.out.println();

	for (int i = 0; i < sjis.length; i++) {
		System.out.printf(" %02x", sjis[i]);
	}
	System.out.println();
 82 a0 82 a2 82 a4 82 a6 82 a8 81 5b 81 7c 87 8a 87 40
 82 a0 82 a2 82 a4 82 a6 82 a8 81 5b 3f 3f 3f

MS932でバイト配列に変換したもの(この時点では文字化けしていない)をSJISでString化した場合、ここでも文字化け(「?」への変換)が発生する。

	System.out.println("M→S :" + new String(m932, "SJIS"));
M→S :あいうえおー???

String#getBytes()やnew String()は、内部ではCharsetDecoderCharsetEncoderクラスが使われている。[2009-02-14]
そちらを直接使えば、変換できない文字コードを「?」にせずにエラーにする、といった処理も出来る。
CharsetDecoderの使用例


Java目次へ戻る / 新機能へ戻る / 技術メモへ戻る
メールの送信先:ひしだま