全角文字が3バイト?! PHP で文字を数えるときの注意点

エンコーディングが Shift_JIS であれば、半角文字は1バイト、全角文字は2バイトですが、エンコーディングが UTF-8 なら 全角文字は 2〜6バイトになります。純粋に文字列のバイト数を知りたい場合、PHP では strlen を使用し、全角も1文字として文字数を数えたい場合は mb_strlen を使用します。UTF-8 でも Shift_JIS のように全角を2バイトとして文字を数えたい場合には、mb_convert_encoding を併用すると良いです。

文字の符号化に必要なバイト数はエンコーディングによって異なる

エンコーディングが Shift_JIS であれば
半角文字を1バイト、全角文字を2バイトで符号化します。
3バイト以上の文字は一つもありません。
Shift_JIS であれば半角文字は1バイト、
全角文字は2バイトとして考えることができます。

エンコーディングが UTF-8 の場合は
1文字を1〜6バイトで符号化します。
半角文字は1バイトですが、
全角文字は2〜6バイトとなります。

HTML文書やプログラムを記述する際、
エンコーディングに UTF-8 を使う場面は少なくありません。
ですから、一律に半角文字は1バイト、
全角文字は2バイトと考えることはできません。

PHP で文字を数える

文字を数える目的は、概ね
次のいずれかだと思います。

  • 文字列のバイト数を数えてデータサイズを知りたい
  • 半角、全角いずれも1文字として文字数を数えたい
  • 文字列の幅を表示領域の幅を揃える計算をするなど、半角文字を1バイト、全角文字を2バイトとして数えたい

それぞれの場合に対応する PHP のサンプルコードを以下に示します。

データサイズを知りたい

strlen文字列のバイト数を返します。


echo strlen('文字列'); // Shift_JIS なら 6、UTF-8 なら 9

文字数を数えたい

半角文字 (1バイトの文字) だけでなく
全角文字 (マルチバイトの文字) も1文字として
文字数を数えたい場合には mb_strlen を使います。

以下の例は、内部文字エンコーディングが UTF-8 の場合です。


echo mb_strlen('文字列'); // 3

内部文字エンコーディングには注意が必要です。
内部文字エンコーディングファイルのエンコーディング
異なると望んだ結果が得られないからです。

内部文字エンコーディングとは、ざっくり言うと
PHP で日本語を扱う関数における (文字エンコーディングの) 設定です。
ですから、PHP プログラムを記述している
ファイルのエンコーディングとは関係がありません。

内部文字エンコーディングは以下のコードで知ることができます。


echo mb_internal_encoding(); // EUC-JP や UTF-8 など

例えば、内部文字エンコーディングが EUC-JP で
PHP のプログラムファイルが UTF-8 であるとします。
文字エンコーディングは一致しません。
当然、計算結果はおかしなものになります。
具体的には ‘文字列’ は 3文字となるべきところ、 6文字となります。

内部文字エンコーディングが UTF-8 ではなく、
PHP のプログラムファイルが UTF-8 である場合には
以下のように文字列のエンコーディングを毎回明記する必要があります。


echo mb_strlen('文字列', 'UTF-8'); // 3

又は、以下のように内部文字エンコーディングを
予め指定
しておく必要があります。


mb_internal_encoding("utf-8");

半角文字を1バイト、全角文字を2バイトとして数えたい

これはエンコーディングが Shift_JIS の場合と
同じ数字が得られれば良いと考えます。
ですから mb_convert_encoding で Shift_JIS に
変換した文字列のバイト数を得れば良いです。


echo strlen( mb_convert_encoding('文字列', 'SJIS', 'UTF-8') ); // 6

転ばぬ先の杖……

strlen

ちなみに、例えば半角30文字、
全角なら15文字分のスペースがあるとして
そこにぴったりと文字を挿入したい……
というのであれば少し気を付けることがあります。

  • 等幅フォントを使う
  • 全角がちょうど全角の2倍の幅になるフォントを使う
  • 全角がちょうど全角の2倍の幅になるフォントサイズを指定する
  • 文字間を狭めたり広げたりしない

文字の幅を揃えるには等幅フォントである必要があります。
その中でも、全角がちょうど全角の2倍の幅になるフォント、
およびフォントサイズである必要があります。
HTML + CSS で考えると font-size は偶数px である必要があり、
pt 指定の場合には dpi によりますが、
96dpi のフォントレンダリングでは 1.5の倍数ptである必要があります。
letter-spacing (文字間) を使うとズレるので使うべきではありません。

半角30文字分の幅 = 全角15文字の幅という
簡単な前提条件が満たすだけにもかかわらず、
考慮すべき点は意外と多です。

以上、お役に立てば幸いです。

お問い合わせについて

業務として技術コンサルティングやシステム設計・開発を行っております。
気になることがありましたらご相談下さい。
ご相談のみで完結する場合、コンサルティング費用の目安は
内容によりますが1時間で5千円〜1万円ていどです。
コンサルティングや開発を検討されるその前に、
まずはお気軽にコメントやメールでご連絡下さい。
ご契約前のコメントやメールでのやりとりは無料です。

お問い合わせフォーム

お急ぎの場合など、ただちに業務対応が必要な場合は、こちらのお問い合わせフォームをご利用ください。かきしちカンパニーお客様窓口が直ちに対応いたします。
※窓口へのお問い合わせ、お見積もりは無料です。


お名前 (必須)

メールアドレス (必須)

題名

メッセージ本文 (必須)

Share

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*