11
votes

Convertir Unicode en ASCII sans changer la longueur de la chaîne (en Java)

Quelle est la meilleure façon de convertir une chaîne de Unicode en ASCII sans changer la longueur (c'est très important dans mon cas)? De plus, les caractères sans aucun problème de conversion doivent être aux mêmes positions que dans la chaîne d'origine. Donc, un "ä" doit être converti en "A" et pas quelque chose de cryptique qui a plus de caractères.

EDIT:
@novovalis - Ces symboles (par exemple des langues asiatiques) devraient simplement être convertis à certains espaces réservés. Je ne suis pas trop intéressé par ces mots ou ce qu'ils veulent dire.

@mtnviewmark - Je dois préserver le nombre de caractères et la position des caractères disponibles d'ASCII sous aucune circonstance.

Voici quelques informations supplémentaires: J'ai quelques outils d'exploration de texte qui ne peuvent traiter que les chaînes ASCII. La plupart du texte qui devrait être traité est en anglais, mais certains contiennent des caractères non ASCII. Je ne suis pas intéressé par ces mots, mais je dois être sûr que les mots que je suis intéressé (ceux qui ne contiennent que des caractères ASCII) sont aux mêmes positions après la conversion de la chaîne.


4 commentaires

Qu'est-ce que vous avez l'intention de convertir 口水 口水? Je ne sais pas comment on pourrait exprimer le concept de poulet de salive en trois caractères ASCII.


Il n'est pas clair - essayez-vous de préserver le nombre de caractères ou le nombre d'octets ... ou peut-être la largeur de la chaîne lorsqu'elle est affichée?


@novalis +1 pour le poulet de la salive :-)


Qu'en est-il des lettres comme þ ou ß?


5 Réponses :


8
votes

Utilisez java.text.normalizer. normaliser () avec normalisateur.form.nfd , puis filtrez les caractères non-ASCII.


3 commentaires

C'est probablement ce que Zardoz voulait réellement, bien qu'il soit inefficace pour des personnages qui ne sont pas dans les pages latines.


+1 Cela ressemble à la meilleure solution au problème (aussi loin que possible de la question).


La normalisation Unicode ne fonctionnera que pour les caractères, qui peut être composée d'un caractère uni latin de l'ASCII Charset et d'une marque de diacritique.



2
votes

CAVEAT: Je ne connais pas Java. Juste un peu sur les ensembles de caractères.

Vous n'êtes pas indiquant que vous utilisez le jeu de caractères utilisez exactement.

mais peu importe que vous utilisez, il est impossible de convertir une chaîne unicode en ASCII et conserver la longueur d'origine et les positions de caractères, simplement parce qu'un jeu de caractères Unicode utilisera Plusieurs octets pour certains personnages (évidemment).

La seule exception que je connaisse serait une chaîne UTF-8 qui contient uniquement des caractères ASCII: cette chaîne sera déjà identique dans UTF-8 et ASCII, car UTF-8 utilise des caractères multibytes uniquement lorsque cela est nécessaire. (Je ne connais pas les autres saveurs unicodes, il peut y avoir d'autres dynamiques).

La seule solution de contournement que je peux voir est d'ajouter un espace à un caractère spécial remplacé par une ASCII, mais qui bousiller la chaîne ( Göteborg dans UTF8 devrait devenir Go teborg pour garder la longueur).

Peut-être que vous voulez élaborer sur ce que vous voulez / besoin d'atteindre, afin que les gens ici puissent suggérer des solutions de contournement.


1 commentaires

Java utilise UTF-16 pour chaînes en interne, donc pour la plupart des langues "occidentales" les plus courantes, le texte original et le texte "ASCII-RÉDUIT" auront la même longueur (sauvegarder la ponctuation impairée occasionnelle).



14
votes

Comme indiqué dans Cette répond, le Le code suivant devrait fonctionner:

??? hello A
true


3 commentaires

Merci ... semble fonctionner presque bien. Mais il y a un problème avec le caractère '^'. Quand il est à l'intérieur d'une chaîne (comme "il ^^ o") il échoue (il est simplement supprimé).


Il suffit de supprimer \\ p {islm} \\ p {issk} de la regex.


Si quelqu'un souhaite supprimer les marques d'interrogation et réduire pleinement le texte aux lettres de base, essayez: "[\\ p {inbasiclatin}] +" (Notez le moyen p {inbasiclatin}] + "(Notez le moyen p}" Non in) ĜǧḧĥJ̈J'ḱKK̈K̸ ǩLLL̈̈̈ẅẍCCC̈C̊C'C̸çillonV̸ĉvvv̈v'v̸bb ̧ǹnn̈n̊n'ńņňñmmm m̈ m̊m̌ǵß



2
votes

Un IssSu avec Normalizer est que le package Pre Java 1.6 est dans Sun.Text, tandis que dans 1,6 son dans le package Java.Text et la signature de la méthode informatique a changé. Donc, si votre application ne fonctionne pas sur les deux plates-formes, vous devrez utiliser la réflexion.

Une solution personnalisée alternative est décrite comme Techniwue 3 ici


0 commentaires

3
votes

Comme Paul Taylor mentionné: il est question d'utiliser Normalizer si vous avez besoin que le projet soit compilable / exécutable en avant 1,6 et également dans 1,6 et plus Java. Vous entrerez dans des problèmes car Normalizer est dans des packages différents ( java.text.normalizer code> (pour 1.6) au lieu de sun.text.normalizer code> (pour la pré-1.6)) et a une méthode différente-signature.

Il est généralement recommandé d'utiliser la réflexion pour invoquer la méthode de normalisation appropriée.Normalize (). ( Vous pourriez être trouvé ici ).
Mais si vous ne voulez pas mettre en désordre de réflexion dans votre code, vous pouvez utiliser bibliothèque ICU4J . Il contient com.ibm.icu.text.normalizer code> classe avec normalisé () code> méthode exécutant le même travail que Java.text.normalizer / sun.text.normalizer. La bibliothèque ICU a (devrait avoir) la mise en œuvre propre de la normalisation afin que vous puissiez partager votre projet avec une bibliothèque et qui devrait être indépendant Java.
L'inconvénient est que la bibliothèque ICU est assez grande. em> p>

Si vous utilisez une classe normale juste pour supprimer des accents / diacritiques de chaînes, il y a aussi une autre manière. Vous pouvez utiliser Apache Commons Lang Langi Bibliothèque (Ver. 3) contenant Stringutils Code > Avec la méthode stripapents () code>: p>

String noAccentsString = org.apache.commons.lang3.StringUtils.stripAccents(s);


0 commentaires