Comment puis-je vérifier si un tableau d'octets contient une chaîne Unicode en Java?
Donné un tableau d'octets, qui est soit une codé en UTF-8 chaîne de caractères ou des données binaires arbitraires, quelles sont les approches qui peuvent être utilisés en Java pour déterminer qui il est?
La matrice peut être généré par le code similaire à:
byte[] utf8 = "Hello World".getBytes("UTF-8");
Alternativement, il peut avoir été généré par un code similaire:
byte[] messageContent = new byte[256];
for (int i = 0; i < messageContent.length; i++) {
messageContent[i] = (byte) i;
}
Le point clé est que nous ne savons pas ce que le tableau contient mais avez besoin de savoir pour remplir la fonction suivante:
public final String getString(final byte[] dataToProcess) {
//Determine whether dataToProcess contains arbitrary data or a UTF-8 encoded string
//If dataToProcess contains arbitrary data then we will BASE64 encode it and return.
//If dataToProcess contains an encoded string then we will decode it and return.
}
Comment ceci pourrait-il être étendu pour couvrir également UTF-16 ou d'autres mécanismes d'encodage?
source d'informationauteur Iain | 2009-07-28
Vous devez vous connecter pour publier un commentaire.
Il n'est pas possible de prendre cette décision avec une précision exacte dans tous les cas, parce qu'une codé en UTF-8 chaîne est une sorte de arbitraire des données binaires, mais vous pouvez regarder pour les séquences d'octets qui sont non valide en UTF-8. Si vous en trouvez, vous savez que ce n'est pas de l'UTF-8.
Si vous le tableau est assez grand, cela devrait fonctionner bien car il est très probable que de telles séquences pour apparaître dans "aléatoire" des données binaires telles que les données compressées ou des fichiers image.
Cependant, il est possible d'obtenir de l'UTF-8 valide les données qui décode dans un univers totalement absurde de la chaîne de caractères (probablement à partir de toutes sortes de différents scripts). C'est la plus probable avec des séquences courtes. Si vous êtes inquiet que vous pourriez avoir à faire une analyse pour voir si les caractères sont des lettres appartiennent tous à la même tableau de code. Puis de nouveau, cela peut produire des résultats faussement négatifs lorsque la validité de la saisie de texte, qui mêle des scripts.
Voici une façon d'utiliser l'UTF-8 "binaire" regex de la W3C site
Comme écrit à l'origine, l'expression régulière est destiné à être utilisé sur un tableau d'octets, mais vous ne pouvez pas le faire avec Java regexes; l'objectif doit être quelque chose qui met en œuvre la CharSequence interface (donc un
char[]
est, trop). En décodant lebyte[]
comme ISO-8859-1, vous créez une Chaîne dans laquelle chaquechar
a le même non signé valeur numérique que l'octet correspondant dans le tableau d'origine.Comme d'autres l'ont souligné, des tests de ce genre ne peut vous dire le
byte[]
pourrait contenir du texte UTF-8, pas qu'il ne. Mais la regex est tellement exhaustif, il semble très peu probable que des données binaires brutes pourrait glisser au-delà. Même un tableau de tous les zéros ne correspondent pas, depuis la regex ne correspond jamais avecNUL
. Si les seules possibilités sont en UTF-8 et binaire, je serais prêt à faire confiance à ce test.Et pendant que vous y êtes, vous pourriez bande de l'UTF-8 BOM si il y en a un; sinon, l'UTF-8 CharsetDecoder va passer à travers comme si c'était du texte.
UTF-16 serait beaucoup plus difficile, parce qu'il y a très peu de séquences d'octets qui sont toujours invalide. Les seuls que je peux penser de la main gauche sont de haute caractères de substitution qui sont absents de la faiblesse de leurs compagnons de substitution, ou vice versa. Au-delà de cela, vous avez besoin d'un peu de contexte pour décider si une séquence donnée est valide. Vous pourriez avoir une Cyrillique lettre suivie d'un idéogramme Chinois, suivi par un smiley face dingbat, mais il serait parfaitement valable UTF-16.
La question suppose qu'il existe une différence fondamentale entre une chaîne et des données binaires. Alors que ce qui est intuitivement donc, il est presque impossible de définir précisément ce que la différence est.
Java Chaîne est une séquence de 16 bits quantités qui correspondent à l'un des (presque) 2**16 Unicode base codepoints. Mais si vous regardez ces 16 bits "caractères", chacun pourrait également représenter un nombre entier, une paire d'octets, un pixel, et ainsi de suite. Les modèles de bits n'ai rien d'intrinsèque à qui dit ce qu'ils représentent.
Maintenant, supposons que vous reformuler votre question en vous demandant une manière de distinguer de TEXTE UTF-8 à partir des données binaires arbitraires. Cela vous aide? En théorie non, car les motifs de bits qui encoder n'importe quel texte écrit peut également être une séquence de numéros. (Il est difficile de dire ce que "arbitraire" signifie vraiment ici. Pouvez-vous me dire comment faire pour tester si un nombre est "arbitraire"?)
Le meilleur que nous pouvons faire ici est la suivante:
En résumé, vous pouvez dire qu'une séquence d'octets est certainement pas en UTF-8 si le décodage échoue. Au-delà, si vous faites des hypothèses sur la langue, vous pouvez dire qu'une séquence d'octets est probablement ou probablement pas un texte UTF-8 document.
De l'OMI, la meilleure chose que vous pouvez faire est d'éviter de se retrouver dans une situation où vous programme doit prendre cette décision. Et si elle ne peut pas l'éviter, de reconnaître que votre programme peut se tromper. Avec l'idée et le travail dur, vous pouvez faire que peu probable, mais la probabilité ne sera jamais égal à zéro.
Si le tableau d'octets commence avec un Marque D'Ordre D'Octet (BOM), alors il sera facile de distinguer ce codage a été utilisé. La norme des classes Java pour le traitement de texte, les flux seront probablement traiter automatiquement pour vous.
Si vous n'avez pas de NOMENCLATURE dans votre octet de données, ce sera nettement plus difficile .NET classes peuvent effectuer des analyses statistiques à essayer de travailler sur l'encodage, mais je pense que c'est sur l'hypothèse que vous savez que vous avez affaire avec les données de texte (il suffit de ne pas savoir qui le codage a été utilisé).
Si vous avez aucun contrôle sur le format de vos données d'entrée votre meilleur choix serait de s'assurer qu'il contient une Marque d'Ordre d'Octet.
Dans la question de départ: Comment puis-je vérifier si un tableau d'octets contient une chaîne Unicode en Java?; J'ai trouvé que le terme Java Unicode est essentiellement se référant à l'Utf16 Unités de Code. Je suis passé par ce problème moi-même et créé un code qui pourrait aider quelqu'un avec ce type de question sur leur esprit, trouver quelques réponses.
J'ai créé 2 méthodes principales, on va afficher Utf-8 Unités de Code et l'autre va créer de Code Utf-16 Unités. De Code Utf-16 Unités est ce que vous rencontrerez avec Java et JavaScript...couramment observés sous la forme "\ud83d"
Pour plus d'aide avec des Unités de Code et essayer de conversion du site web;
https://r12a.github.io/apps/conversion/
Voici le code...
Essayer de les décoder. Si vous n'obtenez pas les erreurs, puis il est une valeur de chaîne UTF-8.
Je pense que Michael a expliqué bien dans sa réponse cela peut être la seule façon de savoir si un tableau d'octets contient toutes les séquences utf-8. Je suis en utilisant suivants du code php
Pris W3.org