マルチバイト文字列関数の罠
ある時、CSVのデータをインポートする処理で不具合が発生。
「2件のデータをまとめてインポートすると1件のみ失敗して、
成功したデータを除いて再度その1件のみをインポートすると成功した」
いやいやそんなアホな。
色々調べた結果、この結論に至りました。
「マルチバイト文字列関数を使用するときは文字コードを指定した方が安全かもしれない」
…うーん…。
今でも微妙に納得いかないのですが。
ちなみに、当該箇所の処理はこうです。
- CSVを取り込む
- 改行区切りで1セットのデータに分割
- カンマ区切りでデータ内の各項目に分割して文字配列にする
- ある項目を全角数字から半角数字に変換(mb_convert_kanaを使用)
- 他項目も含めいろいろ調整したデータをDBに入れたりいろいろする
…という感じなのですが、どうやら全角→半角にする過程で誤変換されたようです。
有効な半角数字にならず、データ不備としてはじかれた、と。
何故か、その2件のデータを一緒に取り込んだ時のみ、片方だけ。
なので特定の文字列が誤変換されるというわけではないですし、問題なく複数レコードが取り込めることだってありました。
(開発時にも、もちろんテストしましたし…)
ともかく、
>全角数字から半角数字に変換(mb_convert_kanaを使用)
これを
$hoge = mb_convert_kana($hoge, "a")
と書いていたのを
$hoge = mb_convert_kana($hoge, "a", "UTF-8")
こうすると改善されました。
誤変換しない場合の方が圧倒的に多いというのがネックですね…。
テストで気付きにくいですし。
他のマルチバイト系関数を使用する際も、文字コードが指定できるものはした方が安全かもしれません。
関係ありそうでしかもちょくちょく使う関数一覧
(リンクは公式マニュアル)
- mb_convert_kana
- 半角・全角間の変換を行う
- mb_strstr / mb_stristr / mb_strpos / mb_strrpos / mb_stripos / mb_strripos
- 文字列Aの中に文字列Bが最初(または最後)に現れる位置を探す
- mb_strlen
- 文字列の文字数を返す
- mb_substr
- 文字列の一部を返す
- mb_strtolower / mb_strtoupper
- 文字列をすべて小文字(または大文字)にする