22
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【PHP】全角半角混在の文字列をバイト数単位で切り出す際にmb_strcutを使うと便利

Last updated at Posted at 2015-05-15

##概要
PHPでバイト数単位で文字列を切り出す際に、思いつくのはsubstrを利用する方法だろう。
このとき半角文字列のみや全角文字列のみを対象に処理をする場合など、1文字あたりのバイト数が同じであれば問題は生じない。
しかし全角半角混在の文字列など1文字あたりのバイト数が異なる文字列をバイト数単位で切り出す際には注意が必要だ。

##問題点
マルチバイトの文字列をsubstrで半端なバイト数単位で切り出すと、
文字列を中途半端な位置で切り出してしまい、不具合の温床となる。

##具体例
文字コードSJISにおいて、

Aあいうえお

という文字列があったとする。(Aは半角、それ以外は全角)
この文字列をsubstrで6バイトで切り出すと、
全角文字(2バイト文字)「う」の1バイト目だけを切り出してしまい文字列が壊れてしまう。
######テストコード

<?php

	$target = "Aあいうえお";// 対象文字列
	$byte   = 6;            // 分割単位: byte
	$enc    = "SJIS";       // 文字コード
	$result = "";           // 処理結果
	$nl     = "<br/>";      // 改行用
	
	// 切り出し処理実行
	$result = substr($target, 0 , $byte);
	
	// 結果の文字数を取得
	$len_mb = mb_strlen($result, 'SJIS');
	
	// 結果のバイト数を取得
	$len = strlen($result);
	
	echo "対象文字列   =  ".$target.$nl;
	echo "切出バイト数 =  ".$byte.$nl;
	echo "結果文字列   =  ".$result.$nl;
	echo "結果文字数   =  ".$len_mb.$nl;
	echo "結果バイト数 =  ".$len.$nl;
?>

######テスト結果

対象文字列 = Aあいうえお
切出バイト数 = 6
結果文字列 = Aあい
結果文字数 = 4   ←表示できない半端なコードが存在することを示している
結果バイト数 = 6

「Aあい」のあとにマルチバイト文字列の断片コードが残ってしまい不具合の原因になってしまう。

##解決方法
substr関数の代わりにmb_strcut関数を使用することで、
1文字に満たない半端なバイトコードを間引いてくれる。

######テストコード


<?php

	$target = "Aあいうえお";// 対象文字列
	$byte   = 6;            // 分割単位: byte
	$enc    = "SJIS";       // 文字コード
	$result = "";           // 処理結果
	$nl     = "<br/>";      // 改行用
	
	// 切り出し処理実行
	$result = mb_strcut($target, 0 , $byte, $enc);
	
	// 結果の文字数を取得
	$len_mb = mb_strlen($result, 'SJIS');
	
	// 結果のバイト数を取得
	$len = strlen($result);
	
	echo "対象文字列   =  ".$target.$nl;
	echo "切出バイト数 =  ".$byte.$nl;
	echo "結果文字列   =  ".$result.$nl;
	echo "結果文字数   =  ".$len_mb.$nl;
	echo "結果バイト数 =  ".$len.$nl;
?>

######テスト結果

対象文字列 = Aあいうえお
切出バイト数 = 6
結果文字列 = Aあい
結果文字数 = 3   ←表示されている文字列と同じ文字数
結果バイト数 = 5

phpのmb_strcut関数を利用することで
6バイト目の文字列は「う」の1バイト目になってしまうため、
半端なバイト数を間引いて、ひとつ前までの切り出しとする結果を得ることができる。

22
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?