はじめに
※ 本記事ではShift_JISを拡張した文字エンコーディングをSJIS系文字エンコーディングと記載しています。
Shift_JIS、Shift-JIS、SJIS、SJIS-win、CP932、MS932、Windows-31J、MS_Kanjiなどなど、、、
SJIS系文字エンコーディングってたくさんありますよね。
「Shift_JISでcsv下さい」って言われたからShift_JISに変換したら「髙」が〜「ハイフン」が〜と言われたことある方は少なくないと思います。
サポートされる文字エンコーディングに記載されている中でよく使用するSJIS系文字エンコーディングは、SJIS、SJIS-win、CP932の3種類だと思います。
サポートされるエンコーディングの概要のShift_JISの説明と注記に「IANA の定義によると、Shift_JIS のコードセットは IBM932 / CP932 とは微妙に異なります。」「CP932 コードマップを使用するには、代わりに SJIS-WIN を使用してください。」と記載されているため今までこのように考えていたんですが、実際は少し違うようです。
エンコーディング名 | 間違った解釈 |
---|---|
SJIS | Shift_JIS |
CP932 | Windows-31J? |
SJIS-win | NEC拡張のCP932? |
しかもサポートされる文字エンコーディングに記載されていない文字エンコーディングでも実際には指定することができます。
下記は全てError、Warning、Noticeが出ることなく変換できます。
<?php
mb_convert_encoding('テスト', 'SJIS');
mb_convert_encoding('テスト', 'SHIFT-JIS');
mb_convert_encoding('テスト', 'Shift_JIS');
mb_convert_encoding('テスト', 'CP932');
mb_convert_encoding('テスト', 'MS932');
mb_convert_encoding('テスト', 'MS_Kanji');
mb_convert_encoding('テスト', 'Windows-31J');
mb_convert_encoding('テスト', 'SJIS-win');
どれが同じでどれが違う文字エンコーディングなのか、、、
このモヤモヤを解消するため、ソースコードを読んで表にまとめてみました。
エンコーディングとエイリアスの表
mime_nameがShift_JISで登録されている文字エンコーディングを全て羅列しています。
エンコーディング名|エイリアス
:--|:--|:--
SJIS|x-sjis, SHIFT-JIS
CP932|MS932, Windows-31J, MS_Kanji
SJIS-win|SJIS-open, SJIS-ms
SJIS-2004|SJIS2004, Shift_JIS-2004
SJIS-mac|MacJapanese, x-Mac-Japanese
SJIS-Mobile#DOCOMO|SJIS-DOCOMO, shift_jis-imode, x-sjis-emoji-docomo
SJIS-Mobile#KDDI|SJIS-KDDI, shift_jis-kddi, x-sjis-emoji-kddi
SJIS-Mobile#SOFTBANK|SJIS-SOFTBANK, shift_jis-softbank, x-sjis-emoji-softbank
エイリアスにShift_JISが登録されている文字エンコーディングはなかったんですが、実際にファイル出力してみたところSJISと同じっぽいです。
UTF-8環境で実行しているためか、CP932とSJIS-winで文字化けする文字に違いはありませんでした。
$file = fopen('test.txt', 'w');
fwrite($file, mb_convert_encoding("髙閒ー−-㌢㏍㍿\n", 'SJIS')); #=> ??ー--???
fwrite($file, mb_convert_encoding("髙閒ー−-㌢㏍㍿\n", 'SHIFT-JIS')); #=> ??ー--???
fwrite($file, mb_convert_encoding("髙閒ー−-㌢㏍㍿\n", 'Shift_JIS')); #=> ??ー--???
fwrite($file, mb_convert_encoding("髙閒ー−-㌢㏍㍿\n", 'CP932')); #=> 髙閒ー--㌢㏍?
fwrite($file, mb_convert_encoding("髙閒ー−-㌢㏍㍿\n", 'MS932')); #=> 髙閒ー--㌢㏍?
fwrite($file, mb_convert_encoding("髙閒ー−-㌢㏍㍿\n", 'SJIS-win')); #=> 髙閒ー--㌢㏍?
fwrite($file, mb_convert_encoding("髙閒ー−-㌢㏍㍿\n", 'Windows-31J')); #=> 髙閒ー--㌢㏍?
fwrite($file, mb_convert_encoding("髙閒ー−-㌢㏍㍿\n", 'MS_Kanji')); #=> 髙閒ー--㌢㏍?
fclose($file);
まとめ
UTF-8からの変換であれば、SJIS or CP932の2択で良さそうです。
Shift_JISのエイリアスであるはずのMS_Kanjiが、PHPではCP932のエイリアスとして登録されているのは不思議な感じがしました。
結局SJIS-winが何を指しているのかはよくわかりませんでした。
そのうち「依存する文字集合」を確認して追記しようと思います。