utf8ストリングのcharを一つ一つ読んでいきたい場合、charsをarrayにsplitするほうが、 mb_substrでストリングの最初から探すほうが効率がいい。 しかし、splitより効率がいい方法は、現在のpointerからnext charを見つける functionを使うことである。 https://stackoverflow.com/questions/3666306/how-to-iterate-utf-8-string-in-php ========================================================================================= Preg split will fail over very large strings with a memory exception and mb_substr is slow indeed, so here is a simple, and effective code, which I'm sure, that you could use: function nextchar($string, &$pointer){ if(!isset($string[$pointer])) return false; $char = ord($string[$pointer]); if($char < 128){ return $string[$pointer++]; }else{ if($char < 224){ $bytes = 2; }elseif($char < 240){ $bytes = 3; }else{ $bytes = 4; } $str = substr($string, $pointer, $bytes); $pointer += $bytes; return $str; } } This I used for looping through a multibyte string char by char and if I change it to the code below, the performance difference is huge: function nextchar($string, &$pointer){ if(!isset($string[$pointer])) return false; return mb_substr($string, $pointer++, 1, 'UTF-8'); } Using it to loop a string for 10000 times with the code below produced a 3 second runtime for the first code and 13 seconds for the second code: function microtime_float(){ list($usec, $sec) = explode(' ', microtime()); return ((float)$usec + (float)$sec); } $source = 'árvíztűrő tükörfúrógépárvíztűrő tükörfúrógépárvíztűrő tükörfúrógépárvíztűrő tükörfúrógépárvíztűrő tükörfúrógép'; $t = Array( 0 => microtime_float() ); for($i = 0; $i < 10000; $i++){ $pointer = 0; while(($chr = nextchar($source, $pointer)) !== false){ //echo $chr; } } $t[] = microtime_float(); echo $t[1] - $t[0].PHP_EOL.PHP_EOL; ========================================================================================= このコードからわかるように、utf8のキャラのByteサイズを判定する方法である。