Discussion:
Tester la validite d'une chaine UTF-8
(trop ancien pour répondre)
Etienne
2010-07-08 12:39:30 UTC
Permalink
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
Olivier Miakinen
2010-07-08 13:15:18 UTC
Permalink
Bonjour,
Post by Etienne
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
Etienne
2010-07-08 15:25:48 UTC
Permalink
Post by Olivier Miakinen
<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.>
$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
Olivier Miakinen
2010-07-08 18:07:52 UTC
Permalink
Post by Etienne
[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.
Post by Etienne
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(
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\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(
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\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
Continuer la lecture sur narkive:
Loading...