PHPでNotice:unserialize()[function.unserialize]:Error at offset問題の解決策が現れる

1665 ワード

今日のPHPの時に何気なく現れてunserialize()関数で変換していつもfalseを返して、私は私の文字列が間違いないことを確認して、何度もテストしてやはり同じで、仕方がなくて、errorを有効にしましたReporting(E_ALL)エラーメッセージを有効にし、
思いがけずNotice:unserialize()[function.unserialize]:Error at offsetの情報を発見しました.私の文字は配列から変換されたので間違いないはずですが、Googleちょっとしてみると、符号化の問題だったのですが、
PHPマニュアルのコメントでこの問題について議論された.
元の私の文字列はデータベースから取り出したもので、元のデータベースに挿入する時私のPHPはANSCII編集で、私がコピーした後にunserialize()のPHPファイルはUTF-8で符号化して、符号化は異なって、だから間違いが現れました.
例:
「トップページはANSCII方式で操作
$arr = array('en' => 'hello', 'cn' => '  ');

$str = serialize($arr);

echo $str;

出力結果:a:2:{s:2:“en”;s:5:“hello”;s:2:“cn”;s:4:“こんにちは”;
そしてUTF-8の符号化方式でテスト
以上のコードの出力結果は、a:2:{s:2:“en”;s:5:“hello”;s:2:“cn”;s:6:“こんにちは”;
"
何が違うのか見てみましょう.中国語の文字が現れると文字の長さが違います.つまりstrlen('こんにちは')は1つ目の符号化では4で、2つ目の符号化では6で、その理由は関連マニュアルを見ることができます. 
一方、unsrialize()は、s:6:「こんにちは」のような6に基づいて文字の長さを判断し、逆シーケンスを行いますが、元は4で、文字の長さが一致しません.つまりoffsetエラーが発生しました.
解決策:
「逆シーケンスにする文字列を一度に変換し、コード
$str = preg_replace('!s:(\d+):"(.*?)";!se', '"s:".strlen("$2").":\"$2\";"', $str );

あるいはunserializeの代わりに自分で決めた関数を使います
function mb_unserialize($serial_str) {

$out = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $serial_str );

return unserialize($out);

}

PHPが面倒なのは符号化の問題ではありません.私たちは文字の問題を処理する時、多くの関数は私たちが自分でカスタマイズして書き換えるので、統一符号化の良い点ではありません.
原文:http://513394217.blog.163.com/blog/static/109791186201251311658501/