JeuWeb - Crée ton jeu par navigateur

Version complète : [Terminé][Snippet, petits modules] Fonction php détectant une chaine UTF8
Vous consultez actuellement la version basse qualité d'un document. Voir la version complète avec le bon formatage.
Énoncé :

Cette fonction prend en argument une chaine et retourner true si elle est en utf8, false, dans le cas contraire.
Le code doit être bien présenté et commenté.
A vos claviers et à vos snippets

Échéance : Lundi (26/08) à 21h.

Technologies autorisées : PHP

Notes : Concours soumis par MP à Anthor, ce n'est que provisoire.

Référence du topic : Référence


Anthor, on attend ta réponse.
Moi n'est reçu aucune réponse !
Néanmoins je vais expliquer les deux fonctions possibles.

La première qui avait été donné utilise la fonction preg_math pour chercher les différents caractères possibles étant spécifiques à l'UTF8.

Code PHP :
function is_utf8$string )
{
    
// From http://w3.org/International/questions/qa-forms-utf-8.html
    
return preg_match'%^(?:
        [\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
    )*$%xs'
$string );

Sur 100000 itérations, il faut 116.26ms.

La deuxième solution compare directement la chaine encodée à elle même, si elles sont égales alors la chaine est en utf8.
Code PHP :
function is_utf8$string )
{
    return (
utf8_encode($string) == $string);

Sur 100000 itérations, il faut 0.8ms. A noter que le temps est à multiplier par 10 si vous utiliser une chaine 10 fois plus grosse alors que pour la première le temps est sensiblement égal.

L'utilisation mémoire peut-être considérée comme égale.
Les deux solutions sont donc utilisables néanmoins sur de longues chaine la première est préférable.

Je n'ai pas testé à partir de combien d'octets la première solution est plus performante.
j'appelle pas ça une réponse 10

Vu la tournure de la chose, je n'ai vraiment répondu que pour expliquer aux personnes qui seraient intéressées.

Les test montrent d'ailleurs que ta solution peut très vite s'essoufler sur de plus longues chaines.
Votre petit dialogue m'a rappelé un truc.
Il faudra aussi que nous instaurions un système de testing de performance précis et commun afin de favoriser l'impartialité 16
oxman a écrit :De plus, utf8_encode est plus rapide que preg_match, je ne sais pas comment tu as testé.
Et ensuite, nos deux codes sont faux pour utf8_encode 2

C'est ce que j'ai dit, la deuxième solution est performante, jusqu'à un certains point, plus la chaine sera longue et plus elle se rapprochera du temps de la première.

De plus oui il n'y a pas le utf8_decode, mais j'ai testé et cela me récupère quand même bien si ma chaine est en utf8, ou pas.

Le test n'a rien de compliqué, il a été pris sur un autre topic de jeu php. J'ai simplement testé les deux fonctions sur un paragraphe de Lorem Ipsum, puis sur 10 paragraphes, et en utf8 et en Iso.
Le preg_match garde le même temps quel que soit la longueur de la chaine, alors que le utf8_encode est proportionnel à la taille de la chaine.
Ha mais ce n'est pas ma fonction, j'ai oublié ton ! en recopiant. 2
Bon le principal c'est qu'elle fonctionne, quand je fais un if(isUTF8($str)) j'avais le bon affichage en ASCII et en UTF8, mais reste à savoir si j'avais bien recopié aussi !

Par contre bizarre. Néanmoins ma chaine la plus petite est ta chaine la plus grande. Et le preg_match n'a pas montré de différence quand je l'ai multiplié par 10 contrairement au utf8_encode. Après c'est peut-être dû à ma machine.

J'ai utilisé exactement le même bench que toi.
Et dans la pratique, je n'utilise que le preg_match.
preg_match devrait être plus rapide sur de grandes chaînes car il s'arrête à la première occurence. (cf la doc de la fonction dans PHP)

Je ne sais pas comment PHP gère les chaines UTF-8 en mémoire mais normalement, une chaine de caractère pleinement encodée en UTF-8 doit théoriquement prendre deux fois plus de place qu'en ASCII et ce même sans contenir de caractères spéciaux..

Prenons par exemple le mot "Module" et vérifions son encodage dans un fichier ASCII puis UTF-8 en utilisant un éditeur Hexa

Dans un fichier ASCII classique, il ressemble à
4D 6F 64 75 6C 65

Dans un fichier UTF-8
4D 00 6F 00 64 00 75 00 6C 00 65 00

Identique visuellement mais différent au niveau binaire.
Dans l'absolu, 'Module' devrait donc être différent de UTF8_Encode('Module').
Pratiquement, PHP ne sait pas faire la distinction car 'Module' === UTF8_Encode('Module') retourne True.

Les fonctions qui sont présentées ici sont plutôt orientées sur la détection de caractères transformés suite à un encodage /décodage UTF-8, pas sur un véritable format UTF-8 des données.
La preg_match bien sûr que si puisqu'elle recherche la présence de caractères encodés sur plusieurs octets, à la différence de UTF8_Encode qui prend en paramètre une chaine encodé en Iso.
URLs de référence