web-dev-qa-db-ja.com

strlen()およびUTF-8エンコーディング

UTF-8エンコーディングとPHPのstrlen()を想定すると、この文字列の長さが4になる可能性はありますか?

Strlen()について知りたいだけで、他の関数については知りません

これは文字列です:

$1�2

自分のコンピューターでテストし、UTF-8エンコーディングを検証しましたが、答えは6です。

Strlenのマニュアルや、UTF-8で読んだもので、上記の文字の一部が1未満と見なされる理由を説明するものは何もありません。

PS:この質問と回答(4)は、Ebayで購入したZCEの模擬テストからのものです。

11
Jon Lyles

投稿した文字列の長さは6文字です:$1�2(ドル記号、数字1、分音記号付きの小文字のi、逆さまの疑問符、半分の分数、数字2)

その文字列のUTF-8表現でstrlen()が呼び出された場合、結果は9になります(おそらく、長さが異なる複数の表現があります)。

ただし、その文字列をISO 8859-1またはCP1252として格納する場合、UTF-8として有効な6バイトの長さのシーケンスがあります。これらの6バイトをUTF-8として再解釈すると、4文字になります:$ 1.2(ドル記号、1桁目、Unicode置換文字、2桁目)。つまり、単一文字「�」のUTF-8エンコーディングは、3文字「�」のISO-8859-1エンコーディングと同じです。

置換文字は、UTF-8デコーダーが有効なUTF-8データではないデータを読み取るときに挿入されることがよくあります。

元の文字列は、複数の誤解の層を介して処理されたようです。非UTF-8データでUTF-8デコーダーを使用して($ 1.2を生成)、次にそのデータを分析するために使用したものを使用して($1�2を生成)。

9
bames53

mb_strlen()を使用するのはどうですか?

http://lt.php.net/manual/en/function.mb-strlen.php

ただし、strlenを使用する必要がある場合は、mbstring.func_overloadディレクティブを2に設定することでウェブサーバーを構成できるため、スクリプトでのstrlenの使用がmb_strlenに自動的に置き換えられます。

19
Anton

マルチバイト文字列関数を使用する必要があります mb_strlen() 次のようになります。

mb_strlen($string, 'UTF-8');
9
Haim Evgi

質問の準備からそれを読むまでのある時点で、いくつかのプロセスが非ASCII文字を壊してしまった可能性があります。そのため、質問は元々4文字の文字列に関するものでした。

シーケンス�は、UTF-8で 置換文字U + FFFD (�)をエンコードし、その結果をlatin1で解釈すると取得されます。この文字は、たとえば、ファイルからテキストを読み取るときに文字をエンコードしないバイトシーケンスの代わりに使用されます。起こったことはおそらくこれです:

Latin1テキストファイルに保存された元の質問には、次のものが含まれていました:$1¢2(¢は任意の非ASCII文字に置き換えることができます)

このファイルは、UTF-8を使用するプログラムによって読み取られました。 ¢に対応するバイトを解釈できなかったため、プログラムはそれを置き換えて、テキスト$1�2を読み取りました。次に、このテキストはUTF-8を使用して書き出され、ファイルに$1\xEF\xBF\xBD2が作成されました。

次に、latin1のファイルを読み取り、$1�2を表示する3番目のプログラムが登場します。

5
Joni

番号。

矛盾による証明を使用します。

strlenはバイトをカウントするため、strlenが4の場合、その文字列には正確に4バイトが含まれている必要があります。

UTF8エンコーディングには文字あたり少なくとも1バイトが必要です。

私たちはそれを確立しました:

  1. 4バイトあります
  2. 文字は1バイト以上で表されます

...まだ、6文字あります...これは矛盾しています。だから、いや。

ただし、完全に明確ではないのは、表示ソフトウェア(Webブラウザなど)が文字列を解釈するために使用している文字セットです。文字を8ビット未満で表すことができるいくつかの珍しいエンコーディングスキームを使用することができます。この場合、4バイトは6文字として表示される可能性があります。したがって、文字列はutf8である可能性がありますが、ブラウザはそれを、たとえば5ビットの文字セットとして解釈することを決定できます。

2
goat

多くのUTF-8文字は、1バイトではなく数バイトを使用します。これがUTF-8の構築方法です(これにより、1つのセットに非常に多くの文字を含めることができます)。

代わりにmb_strlen()を試してください。

1
Madara's Ghost