2010-09-13 6 views
7

Étant donné un nombre décimal ou hexadécimal Unicode pour un caractère qui doit être généré à partir d'un script PHP CLI, comment PHP peut-il le générer? La fonction chr() semble ne pas générer la sortie appropriée. Voici mon script de test, en utilisant le caractère Section Break U + 00A7 (A7 en hexadécimal, 167 en décimal, doit être représentée comme C2 A7 en UTF-8) comme un test:PHP construit une chaîne Unicode?

<?php 
echo "Section sign: ".chr(167)."\n"; // Using CHR function 
echo "Section sign: ".chr(0xA7)."\n"; 
echo "Section sign: ".pack("c", 0xA7)."\n"; // Using pack function? 
echo "Section sign: §\n"; // Copy and paste of the symbol into source code 

La sortie I get (via une session SSH sur le serveur) est:

donc, cela prouve que la police de terminal J'utilise a la section caractère Break en elle, et la connexion SSH envoie le long avec succès, mais chr() ISN » t la construire correctement lors de la construction à partir du numéro de code.

Si je n'ai que le numéro de code et non une option copier/coller, quelles options ai-je?

Répondre

4

PHP n'a aucune connaissance d'Unicode en excluant les fonctions mb_ et iconv. Vous devrez encoder le personnage UTF-8 vous-même.

Pour cela, Wikipedia a un excellent overview sur la façon dont UTF-8 est structuré. Voici une fonction rapide, sale et non testé d'après cet article:

function codepointToUtf8($codepoint) 
{ 
    if ($codepoint < 0x7F) // U+0000-U+007F - 1 byte 
     return chr($codepoint); 
    if ($codepoint < 0x7FF) // U+0080-U+07FF - 2 bytes 
     return chr(0xC0 | ($codepoint >> 6)).chr(0x80 | ($codepoint & 0x3F); 
    if ($codepoint < 0xFFFF) // U+0800-U+FFFF - 3 bytes 
     return chr(0xE0 | ($codepoint >> 12)).chr(0x80 | (($codepoint >> 6) & 0x3F).chr(0x80 | ($codepoint & 0x3F); 
    else // U+010000-U+10FFFF - 4 bytes 
     return chr(0xF0 | ($codepoint >> 18)).chr(0x80 | ($codepoint >> 12) & 0x3F).chr(0x80 | (($codepoint >> 6) & 0x3F).chr(0x80 | ($codepoint & 0x3F); 
} 
+0

Un excellent moyen de le faire serait d'écrire le document PHP en UTF-8 en premier lieu. –

+0

Excellente réponse, Michael; et merci pour la fonction! J'ai créé quelque chose de similaire pour moi en utilisant la fonction pack plutôt que chr à plusieurs reprises. Billy, dans ce but précis, je dois passer d'un code à un personnage; écrire le script PHP en UTF-8 avec les caractères déjà intégrés n'est pas une option. – MidnightLightning

3

Ne pas oublier que UTF-8 est un codage de longueur variable.

§ n'est pas inclus dans les 128 premiers caractères (ASCII) que UTF-8 est capable d'afficher dans un octet. § est un caractère multi-octet en UTF-8, précédé d'un octet c2 qui signifie first byte of a two-byte sequence.. Cela devrait fonctionner:

echo "Section sign: ".chr(0xC2).chr(0xA7)."\n"; 
3
chr 

(PHP 4, PHP 5) 

chr — Return a specific character 

Report a bug 
Description 

string chr (int $ascii) 
Returns a one-character string containing the character specified by ascii. 

Cette fonction complète ord().

important est le mot ascii :) essayer celui-ci:

function uchr ($codes) { 
     if (is_scalar($codes)) $codes= func_get_args(); 
     $str= ''; 
     foreach ($codes as $code) $str.= html_entity_decode('&#'.$code.';',ENT_NOQUOTES,'UTF-8'); 
     return $str; 
    } 
    echo "Section sign: ".uchr(167)."\n"; // Using CHR function 
    echo "Section sign: ".uchr(0xA7)."\n"; 
5

En supposant que vous avez iconv, voici un moyen simple qui ne nécessite pas la mise en œuvre UTF-8 vous:

function unichr($i) { 
    return iconv('UCS-4LE', 'UTF-8', pack('V', $i)); 
} 
0

Je sais que je rouvre un vieux problème résolu, mais depuis que je suis tombé sur ce sujet en cherchant de l'aide, j'ai pensé que je partagerais la solution que j'ai trouvée. La personne initiale posant la question pourrait être intéressée à refactoriser son code pour le mieux.

La reprogrammation manuelle de l'ascii en unicode est comme réinventer la roue, sans parler d'erreurs/potentiel de performance.

La meilleure solution que j'ai trouvé à utiliser:

  1. pack pour créer des valeurs à partir des données d'entrée, en utilisant les codes appropriés pour manger la bonne quantité de données, généralement pack("H*", <input data>) à lire à partir des valeurs hexadécimales
  2. mb_convert_encoding convertir les chaînes ASCII en chaînes unicode, en utilisant mb_convert_encoding(<ASCII string>, "UTF-8"). Si la chaîne d'entrée n'est pas reconnue correctement, un troisième paramètre de cette fonction permet de spécifier le codage d'entrée
Questions connexes