Encodage utf16

Description

PHP supporte mal les caractères supérieurs à 1 octets.
J'ai trouvé plusieurs sources (ou fonctions de PHP) pour contourner certains problèmes mais aucune ne me convenait réellement.

Tout feedback est bienvenue. :)

Source / Exemple :


<?php
/**

  • This File is part of APIS Framework.
  • This program is free software: you can redistribute it and/or modify
  • it under the terms of the GNU General Public License as published by
  • the Free Software Foundation, either version 3 of the License.
  • This program is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  • See the GNU General Public License for more details.
  • You should have received a copy of the GNU General Public License
  • along with this program. If not, see <http://www.gnu.org/licenses/>.
*
  • @category APIS Tools
  • @package None
  • @copyright Copyright (c) 2009-2010 APIS ( VAT ID: FR74 510 367 881 000 16 )
  • @author Salvan Gregory <apis@apieum.com> <+33 (0) 810 200 119>
  • @license http://www.gnu.org/licenses/gpl.txt GPL3
  • @rev 5
  • /
/**
  • @param int $int UTF-16 Char Code
  • @return string the corresponding char hexadecimal value in UTF-8
  • @example for UTF-16:0x4E00 return "\\xE4\\xB8\\x80"
  • /
function strval16( $int ) { if ($int<0x80) { return '\\x'.dechex($int); } elseif ($int<0x110000) { $bin = strrev(decbin($int)); $c = strlen($bin); if ($int>0x7FF) { if($int<0x10000) { if ($c<13)$bin.=str_repeat('0',13-$c); } elseif($c<19) { $bin.=str_repeat('0',19-$c); } } $str = str_split($bin,6); for ($i=0;$i<count($str)-1;$i++) { $str[$i]='\\x'.base_convert('10'.strrev($str[$i]),2,16); } $c = 8-(strlen($str[$i])+$i+1); $str[$i]=str_repeat('1',$i+1).str_repeat('0',$c).strrev($str[$i]); $str[$i]='\\x'.base_convert($str[$i],2,16); $str = array_reverse($str); return implode('',$str); } else { throw new OutOfRangeException("UTF16 accept Chars codes under 0x10FFFF"); } } /**
  • @param int $int UTF-16 Char Code
  • @return string the corresponding char encoded in UTF-8
  • @example for UTF-16:0x4E00 return UTF-8:0xE4 0xB8 0x80 ("\xE4\xB8\x80")
  • @link http://www.ietf.org/rfc/rfc3629.txt See UTF-8 definition for more informations
  • /
function chr16to8( $int ) { if ($int<0x80) { return chr($int); } elseif ($int<0x110000) { $bin = strrev(decbin($int)); $c = strlen($bin); if ($int>0x7FF) { if($int<0x10000) { if($c<13)$bin.=str_repeat('0',13-$c); } elseif($c<19){ $bin.=str_repeat('0',19-$c); } } $str = str_split($bin,6); for ($i=0;$i<count($str)-1;$i++) { $str[$i]=chr(base_convert('10'.strrev($str[$i]),2,10)); } $c = 8-(strlen($str[$i])+$i+1); $str[$i]=str_repeat('1',$i+1).str_repeat('0',$c).strrev($str[$i]); $str[$i]=chr(base_convert($str[$i],2,10)); $str = array_reverse($str); return implode('',$str); } else { throw new OutOfRangeException("UTF16 accept Chars codes under 0x10FFFF"); } } /**
  • @param string $str Text which contains UTF-16 Characters (Raw)
  • @return string $str with UTF-16 characters into html entities
  • /
function html_entity_encode16( $str) { // Chars between 0xD800 and 0xDFFF aren't found if (preg_match_all('@[\x{80}-\x{10FFFF}]@u',$str,$res)!=false) { $res = array_unique($res[0]); foreach($res as $k=>$v) { $v = str_split(bin2hex($v),2); $c = count($v)-1; for ($i=$c;$i>0;$i--) { $v[$i]=substr(base_convert($v[$i],16,2),-6); } $v[0]=substr(base_convert($v[0],16,2),$c-6); $res1[$k]= '&#'.base_convert(implode('',$v),2,10).';'; } return str_replace($res,$res1,$str); } return $str; } /**
  • @param string $str Text which contains html characters entities
  • @return string $str with UTF-16 raw characters.
  • /
function html_entity_decode16( $str) { if (preg_match_all('@&#[0-9a-f]+;@i',$str,$res)!=false) { $res = array_unique($res[0]); foreach($res as $k=>$v) { $res1[$k]=chr16to8(intval(substr($v,2,strlen($v)-1))); } return str_replace($res,$res1,$str); } return $str; }

Conclusion :


Ce code permet d'afficher en UTF-8 les caractères supérieurs à 1 octets mais aussi de les protéger pour les afficher dans une page web.
Il se compose de 4 fonctions :
  • strval16 qui retourne la séquence de valeurs hexadécimales représentant un caractère UTF-16 convertit en UTF-8.
  • chr16to8 qui retourne un caractère UTF8 à partir de son code UTF-16 (en hexa ou décimal jusqu'à 0x0010FFFF [4o] )
  • html_entity_encode16 qui remplace les caractères UTF-16 d'une chaine par l'entité de caractère HTLM correspondante.
  • html_entity_decode16 qui remplace les entités de caractères HTML par le caractère UTF-16 correspondant.

Le ZIP contient en plus les tests unitaires (basiques) dont le résultat est ci-joint en capture.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.