3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[PHP]半角英数のみのファイルの文字コードを変換しようとしてハマったので備忘録

Posted at

文字コードを変換するコードを書いていて、表題の通り、ハマりましたので、備忘録として書いておきます。

環境

  • OS: Amazon Linux2
  • PHP: 7.4.14

詳細

UTF-8のファイルをもとに、SJISでファイル出力するコードを書きました(確認用のコードも含めてます)。

convertEncoding.php
$data_org = file_get_contents('./files/utf8_sample.csv');
echo "変換前の文字コード:".mb_detect_encoding($data_org,"UTF-8, ASCII, SJIS")."\n";
file_put_contents('./files/sjis_sample.csv',  mb_convert_encoding($data_org, "SJIS"), FILE_APPEND | LOCK_EX);
$data_conv = file_get_contents('./files/sjis_sample.csv');
echo "変換後の文字コード:".mb_detect_encoding($data_conv,"UTF-8, ASCII, SJIS")."\n";

半角英数のみのファイルを用いた場合

変換前のファイルの内容は以下の通り。文字コードはUTF-8です。

utf8_sample.csv
id,sex,age,amount,category
00000003,m,31,00002001,food
00000003,m,31,00007569,clothes
00000012,f,24,00001482,clothes
00000013,m,41,00012349,other
00000016,f,53,00001297,book
00000016,f,53,00005264,food

で、変換前のファイルを所定の場所に置き、PHPファイルを実行すると、以下のような結果に。

コンソール出力結果
$ php fileEncoding.php
変換前の文字コード:UTF-8
変換後の文字コード:UTF-8

ん? 変換されてない?

調べていくうちに、半角英数の場合は、どの文字コードでも(今回の比較対象:JIS, SJIS, EUC, UTF-8, UTF-16)、同じ文字数字の組み合わせになることが判明(当たり前っちゃ当たり前な気もしますが)。

Unicode対応 文字コード表

辺りを見ると、一目瞭然!

文字エンコーディングを検出する関数mb_detect_encodingでは、第2引数に指定した文字エンコーディングをリストを先頭から順番に一致するものがないか検索するようなので、試しに、convertEncoding.phpのmb_detect_encodingの第2引数の順序を変えてみるとコンソール出力結果は、以下のようになりました。

ASCIIを先頭にした場合
$ php fileEncoding.php
変換前の文字コード:ASCII
変換後の文字コード:ASCII
SJISを先頭にした場合
$ php fileEncoding.php
変換前の文字コード:SJIS
変換後の文字コード:SJIS

変換対象が半角英数の場合は、どの文字エンコーディングでも、表現が共通しているから、第2引数の先頭に指定したものに合致すると見なされるわけですね。

ちなみに、nkfコマンドで文字コードの確認をすると以下の通りに。

nkfコマンドの実行結果
# 変換前のファイル
$ nkf --guess ./files/utf8_sample.csv
ASCII (CRLF)
# 変換後のファイル
$ nkf --guess ./files/utf8_sample.csv
ASCII (CRLF)

UTF-8も、SJISもASCIIの拡張だからかな・・?

日本語入りのファイルを用いた場合

原因が分かったところで、変換前のファイルの一部を日本語にしてみます。今回も、文字コードはUTF-8です。

utf8_sample.csv
id,sex,age,amount,category
00000003,m,31,00002001,食品
00000003,m,31,00007569,衣類
00000012,f,24,00001482,衣類
00000013,m,41,00012349,その他
00000016,f,53,00001297,
00000016,f,53,00005264,食品

再度、convertEncoding.phpを実行!

コンソール出力結果
$ php fileEncoding.php
変換前の文字コード:UTF-8
変換後の文字コード:SJIS

今度はうまくいきました!

nkfコマンドでも確認してみると・・・

nkfコマンドの実行結果
$ nkf --guess ./files/utf8_sample.csv
UTF-8 (CRLF)
# 変換後のファイル
$ nkf --guess ./files/utf8_sample.csv
Shift_JIS (CRLF)

こちらも想定通り!!

結論

  • 文字コードを正しく理解する!
  • 文字コード変換するなら、対象の言語を用いる!

につきますね。

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?