【PHP】
strpos、mb_strposで
日本語がヒットしない、マッチしない、
検索できない時の対処法
英数字はヒットするし、スペルミスもないのに~と頭を抱えてしまいました。
ここでは、その時の意外な原因と解決方法を備忘録を兼ねてメモっています。
ヒントとなった記事はこちら。大変助かりました。
strpos、mb_strposで
日本語がヒットしない、マッチしない、
検索できない原因は?
結論から書くと、今回の原因はファイルの文字コードが「ShiftJIS」だったことでした。
この時の作業内容は、ファイルAからファイルBを読み込み、特定の文字列の有無をstrpos関数やmb_strpos関数で調べるといったもの。
作業ファイルAは「UTF-8」形式でファイル作成していたのですが、読み込むファイルBは自動生成ファイルで、文字コードを確認していませんでした。
調べてみたところ、ファイルの文字コードによって1文字のバイト数は異なるそう。
半角英数字は「UTF-8」でも「ShiftJIS」でも1バイトですが、日本語(全角文字)は「ShiftJIS」で2バイト、「UTF-8」では3~8バイトの可変長になっているのだそうです。
strpos関数では、1文字を1バイトとして計算しています。
mb_strpos関数では、1文字で可変長のマルチバイトな日本語に対応している、というわけですね。
ですが、文字コードの異なる「UTF-8」「ShiftJIS」間では、正しく動作しません。
解決方法
「UTF-8」「ShiftJIS」など、異なる文字コードファイル間でデータを扱う場合は、正しく取り出せるデータ形式に変換する必要があります。
読み込むファイルの文字コードを「UTF-8」にすることでも解決できますが、今回は「mb_convert_encoding()」を使って「ShiftJIS」形式のデータを「UTF-8」形式に変換することで解決できました。
「ShiftJIS」ファイルを生成するたびに、文字コードを変更する手間が省けます。
ob_start();
readfile('sample.txt');
$txt = ob_get_contents();
ob_end_clean();
$txt = mb_convert_encoding($txt,"utf-8","sjis-win");
これで、strpos関数でもmb_strpos関数でも、日本語を含む文字列を検索することができました。