mb_substrが遅いので対応策
MySQLのダンプデータでエスケープ文字の対応をしていたらmb_substrが遅いことが判明その時に対応した内容をメモ
mb_substr
文字列の一部を得る
mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_encoding() ]] ) : string
//テストデータ1000文字 $value = '1234567890あいうえおかきくけこabcdefghijklmnopqrstuvwxyz・・・'; $nStart = microtime(true); $len = mb_strlen($value, 'UTF-8'); for ($nIdx = 0; $nIdx < $len; $nIdx++) { $char = mb_substr($value, $nIdx, 1, 'UTF-8'); //処理 } $nEnd = microtime(true); echo $nEnd - $nStart;
5回テスト 0.0044329166412354 0.0036618709564209 0.0022969245910645 0.0045580863952637 0.0032129287719727 平均 0.00363
preg_split
正規表現で文字列を分割する
preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] ) : array
preg_splitを使ってmb_substrの代替え
//テストデータ1000文字 $value = '1234567890あいうえおかきくけこabcdefghijklmnopqrstuvwxyz・・・'; $nStart = microtime(true); $arrChar = preg_split('//u', $value, -1, PREG_SPLIT_NO_EMPTY); foreach ($arrChar as $key=>$row) { $char = $row; //処理 } $nEnd = microtime(true); echo $nEnd - $nStart;
5回テスト 0.00013303756713867 0.0001521110534668 0.00013303756713867 0.00014901161193848 0.00014805793762207 平均 0.00014
※結果、文字列から1文字づつ抽出して処理するのは「mb_substr」より「preg_split」を使ったほうが26倍速い結果となりました。
実際にエスケープ文字の対応をしたソースコード
//\(エスケープ)連続 $pos = mb_strpos($row, '\\', 0, 'UTF-8'); if ($pos !== false) { $rowBk = ''; $value = ''; $count = 0; $arrChar = preg_split('//u', $row, -1, PREG_SPLIT_NO_EMPTY);//mb_substrが遅いのでpreg_splitを使用 foreach ($arrChar as $key2=>$row2) { $char = $row2; if ($char === '\\') { $value .= $char; $count++; } else { if (strlen($value) === 0) { $rowBk .= $char; } else { $value = $value.$char; $value = str_replace('\\\\', '\\', $value); //奇数回 if (($count % 2) !== 0) { if ($char === '\'') { //シングルクォーテーション $value = str_replace("\'", "''", $value); } else if ($char === '"') { //ダブルクォーテーション $value = str_replace('\"', '"', $value); } else if ($char === 'n') { //改行 $value = str_replace('\n', "\n", $value); } } $rowBk .= $value; $count = 0; $value = ''; } } } $row = $rowBk; }