Tester la validite d'une chaine UTF-8

3 réponses
Avatar
Etienne
Salut.

J'encode des charset dans tout les sens, et il arrive des cas très rare,
ou j'ai une chaine considérée comme UTF-8 alors qu'elle ne l'est pas.

J'ai besoin de pouvoir détecter ces chaînes.

j'ai cherché partout sans succès.
comment pourrais détecter ces chaines afin de les éliminer.

Merci
Etienne

3 réponses

Avatar
Olivier Miakinen
Bonjour,

Le 08/07/2010 14:39, Etienne a écrit :

J'encode des charset dans tout les sens, et il arrive des cas très rare,
ou j'ai une chaine considérée comme UTF-8 alors qu'elle ne l'est pas.

J'ai besoin de pouvoir détecter ces chaînes.



<cit. http://fr.wikipedia.org/wiki/UTF-8>
Représentation binaire UTF-8 Signification
0xxxxxxx 1 octet codant 1 à 7 bits
110xxxxx 10xxxxxx 2 octets codant 8 à 11 bits
1110xxxx 10xxxxxx 10xxxxxx 3 octets codant 12 à 16 bits
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4 octets codant 17 à 21 bits
</cit.>

Tester ceci n'est pas très difficile. Par exemple (code non testé) :

$A = "[x01-x7f]"; // ASCII 7 bits (sauf nul) -- 1 octet
$C = "[x80-xbf]"; // 10xxxxxx = octet de continuation
$B2 = "[xc0-xdf]"; // 110xxxxx = début de séquence à 2 octets
$B3 = "[xe0-xef]"; // 1110xxxx = début de séquence à 3 octets
$B4 = "[xf0-xf7]"; // 11110xxx = début de séquence à 4 octets
$re = "/^($A|$B2$C|$B3$C{2}|$B4$C{3})*$/";

if (preg_match($re, $chaine)) {
// Syntaxe de base UTF-8 validée.
// Pour une validation complète il faudrait rajouter certaines
// contraintes, mais ce n'est peut-être pas indispensable.
} else {
// Cette chaîne n'est pas en UTF-8.
}

Cordialement,
--
Olivier Miakinen
Avatar
Etienne
Le 08/07/2010 15:15, Olivier Miakinen a écrit :
Le 08/07/2010 14:39, Etienne a écrit :

<cit. http://fr.wikipedia.org/wiki/UTF-8>
Représentation binaire UTF-8 Signification
0xxxxxxx 1 octet codant 1 à 7 bits
110xxxxx 10xxxxxx 2 octets codant 8 à 11 bits
1110xxxx 10xxxxxx 10xxxxxx 3 octets codant 12 à 16 bits
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4 octets codant 17 à 21 bits
</cit.>

Tester ceci n'est pas très difficile. Par exemple (code non testé) :

$A = "[x01-x7f]"; // ASCII 7 bits (sauf nul) -- 1 octet
$C = "[x80-xbf]"; // 10xxxxxx = octet de continuation
$B2 = "[xc0-xdf]"; // 110xxxxx = début de séquence à 2 octets
$B3 = "[xe0-xef]"; // 1110xxxx = début de séquence à 3 octets
$B4 = "[xf0-xf7]"; // 11110xxx = début de séquence à 4 octets
$re = "/^($A|$B2$C|$B3$C{2}|$B4$C{3})*$/";

if (preg_match($re, $chaine)) {
// Syntaxe de base UTF-8 validée.
// Pour une validation complète il faudrait rajouter certaines
// contraintes, mais ce n'est peut-être pas indispensable.
} else {
// Cette chaîne n'est pas en UTF-8.
}

Cordialement,



Merci.
je vais essayer...
j'espère que cela va solutionner mon problème...
ca serait top :)

Merci encore
Etienne
Avatar
Olivier Miakinen
Le 08/07/2010 17:25, Etienne a écrit :

[citation intégrale]





Je ne sais pas si tu le sais, mais les règles de citation en vigueur sur
toute la hiérarchie le sont d'autant plus dans le forums modérés.
Quelques lignes de plus, et ton article était refusé pour citation
excessive.

Voir <http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html>, en
particulier les paragraphes 3a et 3b.

Merci.
je vais essayer...
j'espère que cela va solutionner mon problème...
ca serait top :)



J'ai trouvé encore mieux :

<cit. http://www.w3.org/International/questions/qa-forms-utf-8>
$field =~
m/A(
[x09x0Ax0Dx20-x7E] # ASCII
| [xC2-xDF][x80-xBF] # non-overlong 2-byte
| xE0[xA0-xBF][x80-xBF] # excluding overlongs
| [xE1-xECxEExEF][x80-xBF]{2} # straight 3-byte
| xED[x80-x9F][x80-xBF] # excluding surrogates
| xF0[x90-xBF][x80-xBF]{2} # planes 1-3
| [xF1-xF3][x80-xBF]{3} # planes 4-15
| xF4[x80-x8F][x80-xBF]{2} # plane 16
)*z/x;
</cit.>

J'ai vérifié, cela correspond aux seuls encodages UTF-8 permis des
caractères 09 (tabulation), 0A (saut de ligne), 0D (retour chariot),
20 à 7E (ASCII imprimable), 80 à D7FF et E000 à 10FFFF (c'est-à-dire
tout le reste sauf les surrogates D800 à DFFF). Il me semble qu'ils
auraient pu exclure aussi les commandes C1, soit 80 à 9F, mais bon,
ce n'est pas très gênant. Idem pour les non-caractères du style FFFE
et FFFF.

En PHP cela donne :

================================================================ $re = "/A(
[x09x0Ax0Dx20-x7E] # ASCII
| [xC2-xDF][x80-xBF] # non-overlong 2-byte
| xE0[xA0-xBF][x80-xBF] # excluding overlongs
| [xE1-xECxEExEF][x80-xBF]{2} # straight 3-byte
| xED[x80-x9F][x80-xBF] # excluding surrogates
| xF0[x90-xBF][x80-xBF]{2} # planes 1-3
| [xF1-xF3][x80-xBF]{3} # planes 4-15
| xF4[x80-x8F][x80-xBF]{2} # plane 16
)*z/x";

if (preg_match($re, $chaine)) {
// Syntaxe UTF-8 validée, sans encodage
// « overlong » ni « surrogates » :
// U+0009, U+000A, U+000D, U+0020 .. U+007E,
// U+0080 .. U+D7FF, U+E000 .. U+10FFFF.
} else {
// Cette chaîne n'est pas en UTF-8.
}
================================================================
Cordialement,
--
Olivier Miakinen