11月 302011
近年はWebで文字化けを見ることがずいぶんと減ったかと思いますが、古いシステムを使っていたり、メールを送信したり、ガラケー向けのWebサイトを作ったりする場合に、機種依存文字(NEC機種依存文字、IBM拡張文字など)に困ることがあります。
ちなみに携帯Twitterでは機種依存文字がガラケーで表示されません。
Twitter / @loglesslove: 濵﨑髙德(はまさきたかのり)さんは携帯Twitterで表示される?
そんなわけで、全部の機種依存文字を判定するにはどうすればいいんだ?と思ってPHPで作ってみました。
機種依存文字判定ツール
判定は文字を SJIS と SJIS-win にそれぞれエンコードして、その結果の文字列を比較して行っています。
以下のクラスのインスタンスを作成して、文字列を与えて処理する形です。
class ExternalString { private $_encoding = 'UTF-8'; /** * 外字インスタンスの配列 * @var array */ private $_externalCharacters; /** * コンストラクタ * 文字列をセットすると外字インスタンスの配列を作る * @param string $string 文字列 */ public function __construct($string = null) { $this->_string = $string; $this->_externalCharacters = $this->_partStringAndJudgeExternal($string); } /** * 文字列をセットするついでに外字インスタンスの配列を作る * @param string $string */ public function setString($string) { $this->_externalCharacters = $this->_partStringAndJudgeExternal($string); } /** * 文字列を文字に分解して外字インスタンスをつくり、その配列として返す * @param string $string */ private function _partStringAndJudgeExternal($string) { $chars = array(); $length = mb_strlen($string, $this->_encoding); for ($i = 0; $i < $length; $i++) { $char = mb_substr($string, $i, 1, $this->_encoding); $exChar = new ExternalCharacter($char); $external = strcmp(mb_convert_encoding($char, 'SJIS', $this->_encoding), mb_convert_encoding($char, 'SJIS-win', $this->_encoding)) !== 0; $exChar->setExternal($external); $chars[$i] = $exChar; } return $chars; } /** * 外字を取り除く * @return array */ public function filter() { return $this->_getEitherChars(false); } /** * 外字だけ返す * @return array */ public function pickup() { return $this->_getEitherChars(true); } /** * 外字か通常の文字かのどちらかを配列として返す * @param boolean $external * @return array */ private function _getEitherChars($external) { $chars = array(); foreach ($this->_externalCharacters as $key => $exChar) { if ($exChar->isExternal() === $external) { $chars[] = $exChar->getCharacter(); } } return $chars; } /** * 外字に色(のスタイル)を付けて文字列として返す * @param string $color * @return string */ public function getColoredString($color = '#ffff00') { if (preg_match('/^#[0-9a-f]{6}$/', $color) == 0) { $color = '#ffff00'; } $chars = array(); foreach ($this->_externalCharacters as $key => $exChar) { $char = htmlspecialchars($exChar->getCharacter()); if ($exChar->isExternal()) { $char = '<span style="background-color: ' . $color . ';">' . $char . '</span>'; } $chars[] = $char; } $string = implode('', $chars); return $string; } } class ExternalCharacter { /** * 文字 * @var string */ private $_character; /** * 外字フラグ * @var boolean */ private $_external; /** * コンストラクタ * @param string $character */ public function __construct($character = null) { $this->_character = $character; $this->_external = false; } /** * 文字setter * @param string $character */ public function setCharacter($character) { $this->_character = $character; } /** * 外字フラグsetter * @param boolean $external */ public function setExternal($external) { $this->_external = $external; } /** * 文字getter * @return string */ public function getCharacter() { return $this->_character; } /** * 外字かどうかを言う * @return boolean */ public function isExternal() { return $this->_external; } }
あとは以下のようにして文字を処理して取り出しています。
$xStr = new ExternalString($string); // インスタンス生成 $coloredString = $xStr->getColoredString(); // 色付き文字列 $regularString = implode("", $xStr->filter()); // 機種依存文字除く文字 $externalString = implode("", $xStr->pickup()); // 機種依存文字
※ソース・コメントはもっといい書き方があれば修正すると思います。(文字列で返すか配列で返すかというところもそのうち。)
Sorry, the comment form is closed at this time.