7
votes

Détecter si une chaîne était à double codée dans UTF-8

J'ai besoin de traiter une grande liste de cordes courtes (principalement en russe, mais toute autre langue est possible, y compris des ordures aléatoires d'un chat marchant sur le clavier).

Certaines de ces chaînes seront codées dans UTF-8 deux fois.

J'ai besoin de détecter de manière fiable si une chaîne donnée est à double codée et le réparer. Je devrais le faire sans utiliser de bibliothèques externes, simplement en inspectant les octets. La détection doit être aussi rapide que possible.

La question est la suivante: Comment détecter qu'une chaîne donnée a été codée dans UTF-8 deux fois?

mise à jour: >

Les chaînes originales sont dans UTF-8. Voici le code AS3 qui fait le second encodage (malheureusement, je n'ai pas de contrôle sur le code client, donc je ne peux donc pas résoudre ce problème): xxx

note tolowercase () appel. Peut-être que cela peut aider?


3 commentaires

Qu'entendez-vous par double codé dans utf8 ??


@Martin: FWIW, ma réponse suppose que cela signifie prendre du texte dans le codage X, le transformer en octets UTF-8, puis prendre ces octets, les réinterpréter comme codant x et transformer cela en octets UTF-8. En d'autres termes, que se passe-t-il lorsque vous interprétez de manière incorrecte un fichier de fichiers UTF-8 comme ISO-8859-1 (ou autre), puis "le convertir en UTF-8".


Eh bien, le texte original était dans UTF-8 et il est à nouveau codé dans UTF-8 par la bibliothèque client de Buggy. (Je vais essayer d'obtenir plus de détails sur ce qui codant de cette bibliothèque supposé le texte.)


3 Réponses :


7
votes

En principe, vous ne pouvez pas, surtout pour permettre aux ordures cates.

Vous ne dites pas ce que le codage de caractères d'origine des données était avant qu'il a été codé UTF-8 une ou deux fois. Je suppose que cp1251 (ou du moins que CP1251 est l'une des possibilités) car c'est un cas assez délicat.

Prendre un caractère non ASCII. UTF-8 encoder. Vous obtenez des octets et tous ces octets sont des caractères valides dans CP1251, à moins que l'un d'entre eux ne soit 0x98, le seul trou de CP1251.

Donc, si vous convertissez ces octets de CP1251 en UTF-8, le résultat est exactement le même que si vous avez correctement codé UTF-8 codé une chaîne CP1251 composée de ces caractères russes. Il n'ya aucun moyen de dire si le résultat provient de manière incorrecte à double codage d'un caractère, ou correctement codant sur 2 caractères.

Si vous avez un certain contrôle sur les données d'origine, vous pouvez mettre un nom à l'heure du début. Ensuite, quand il vous revient, inspectez les octets initiaux pour voir si vous avez une naissance UTF-8, ou le résultat d'un codage incorrect à double codage. Mais je suppose que vous n'avez probablement pas ce genre de contrôle sur le texte original.

En pratique, vous pouvez deviner - UTF-8 décode et ensuite:

(a) Regardez les fréquences de caractères, les fréquences de paires de caractères, les nombres de caractères non imprimables. Cela pourrait vous permettre de déclarer provisoirement une non-sens, et donc éventuellement à double codation. Avec suffisamment de caractères non imprimables, il peut être si absurde que vous ne pouviez pas le taper de manière réaliste même en écrasant au clavier, à moins que votre clé alt était bloquée.

(b) tente la deuxième décode. C'est-à-dire à partir des points de code Unicode que vous avez obtenu en décodage de vos données UTF-8, d'abord le coder à CP1251 (ou autre), puis décodez le résultat de l'UTF-8. Si l'une ou l'autre étape échoue (en raison de séquences non valides d'octets), elle n'était certainement pas à double codée, du moins de ne pas utiliser CP1251 comme interprétation défectueuse.

C'est plus ou moins ce que vous faites si vous avez des octets qui pourraient être UTF-8 ou pourraient être CP1251, et vous ne savez pas lequel.

Vous obtiendrez des faux positifs pour les ordures cates codées à une seule-codée indiscernables des données à double codée, et peut-être un très peu de faux négatifs pour les données à double codation, mais qu'après le premier encodé par Fluke ressemblait à la russe. .

Si votre codage d'origine a plus de trous de la CP1251, vous aurez moins de faux négatifs.

Les codages de caractères sont durs.


2 commentaires

Vous avez raison, je n'ai pas de contrôle sur les chaînes d'origine. Mais j'ai mis à jour la question avec plus d'informations, peut-être que cela aidera.


Il n'y a rien de spécial sur la nomenclature codée à UTF-8 le marquant comme UTF-8 au lieu de déchets dans tout autre codage.



4
votes

Voici un algorithme PHP qui a fonctionné pour moi.

Il est préférable de réparer vos données, mais si vous ne pouvez pas voici une astuce: xxx

La bibliothèque que j'utilise est la suivante: https://github.com/neitanod/foreutf8/


1 commentaires

Quels sont les taux d'erreur pour l'entrée attendue?



0
votes
if (mb_detect_encoding(mb_convert_encoding($string,'Windows-1251','UTF-8'),'Windows-1251,UTF-8',true) === 'UTF-8' ){
  $string=mb_convert_encoding($string,'Windows-1251','UTF-8');
};

1 commentaires

Quels sont les taux d'erreur pour l'entrée attendue?