Existe-t-il un moyen simple d'éviter de traiter les problèmes de codage de texte?
Existe-t-il un moyen simple d'éviter de traiter les problèmes de codage de texte?
Réponses:
Vous ne pouvez pas vraiment éviter de traiter les problèmes d'encodage de texte, mais il existe des solutions existantes dans Apache Commons:
Reader
à InputStream
:ReaderInputStream
Writer
à OutputStream
:WriterOutputStream
Il vous suffit de choisir l'encodage de votre choix.
Si vous commencez avec une chaîne, vous pouvez également effectuer les opérations suivantes:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
ReaderInputStream
implémentation nécessiterait moins de mémoire - il ne devrait pas être nécessaire de stocker tous les octets d'un tableau à la fois.
Eh bien, un Reader traite des caractères et un InputStream traite des octets. Le codage spécifie comment vous souhaitez représenter vos caractères sous forme d'octets, vous ne pouvez donc pas vraiment ignorer le problème. Quant à éviter les problèmes, mon avis est le suivant: choisissez un jeu de caractères (par exemple "UTF-8") et respectez-le.
En ce qui concerne la manière de le faire, comme cela a été souligné, « les noms évidents de ces classes sont ReaderInputStream et WriterOutputStream . » Étonnamment, « ils ne sont pas inclus dans la bibliothèque Java » même si les classes «opposées», InputStreamReader et OutputStreamWriter sont inclus.
Ainsi, beaucoup de gens ont mis au point leurs propres implémentations, y compris Apache Commons IO . En fonction des problèmes de licence, vous pourrez probablement inclure la bibliothèque commons-io dans votre projet, ou même copier une partie du code source (qui est téléchargeable ici ).
Comme vous pouvez le voir, la documentation des deux classes indique que «tous les encodages de charset pris en charge par le JRE sont gérés correctement».
NB Un commentaire sur l'une des autres réponses ici mentionne ce bug . Mais cela affecte la classe Apache Ant ReaderInputStream ( ici ), pas la classe Apache Commons IO ReaderInputStream.
Notez également que, si vous commencez avec une chaîne, vous pouvez ignorer la création d'un StringReader et créer un InputStream en une seule étape à l'aide de org.apache.commons.io.IOUtils de Commons IO comme ceci:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Bien sûr, vous devez toujours penser à l'encodage du texte, mais au moins la conversion se fait en une seule étape.
new ByteArrayInputStream(report.toString().getBytes("utf-8"))
, ce qui implique l'allocation de deux copies supplémentaires du rapport en mémoire. Si le rapport est volumineux, il est mauvais. Voyez ma réponse.
Utilisation:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
Cette méthode ne nécessite pas de conversion initiale vers String
, puis vers byte[]
, ce qui alloue beaucoup plus de mémoire de tas, au cas où le rapport serait volumineux. Il se convertit en octets à la volée lorsque le flux est lu, directement à partir du StringBuffer.
Il utilise CharSequenceInputStream du projet Apache Commons IO.
Les noms évidents de ces classes sont ReaderInputStream et WriterOutputStream. Malheureusement, ceux-ci ne sont pas inclus dans la bibliothèque Java. Cependant, Google est votre ami.
Je ne suis pas sûr que cela va contourner tous les problèmes d'encodage de texte, qui sont cauchemardesques.
Il y a un RFE, mais il est fermé, ne résoudra pas.
Vous ne pouvez pas éviter les problèmes d'encodage de texte, mais Apache commons-io a
Notez que ce sont les bibliothèques auxquelles il est fait référence dans la réponse de Peter sur koders.com, juste des liens vers la bibliothèque au lieu du code source.
Essayez-vous d'écrire le contenu d'un Reader
dans un OutputStream
? Si tel est le cas, vous aurez plus de facilité à encapsuler le OutputStream
dans un OutputStreamWriter
et à écrire le char
s du Reader
vers le Writer
, au lieu d'essayer de convertir le lecteur en un InputStream
:
final Writer writer = new BufferedWriter(new OutputStreamWriter( urlConnection.getOutputStream(), "UTF-8" ) );
int charsRead;
char[] cbuf = new char[1024];
while ((charsRead = data.read(cbuf)) != -1) {
writer.write(cbuf, 0, charsRead);
}
writer.flush();
// don't forget to close the writer in a finally {} block
Un avertissement lors de l'utilisation de WriterOutputStream - il ne gère pas toujours l'écriture de données binaires dans un fichier correctement / de la même manière qu'un flux de sortie normal. J'ai eu un problème avec cela qui m'a pris un certain temps à retrouver.
Si vous le pouvez, je vous recommande d'utiliser un flux de sortie comme base, et si vous avez besoin d'écrire des chaînes, utilisez un wrapper OUtputStreamWriter autour du flux pour le faire. Il est beaucoup plus fiable de convertir du texte en octets que l'inverse, ce qui explique probablement pourquoi WriterOutputStream ne fait pas partie de la bibliothèque Java standard
Vous pouvez utiliser Cactoos (pas de méthodes statiques, uniquement des objets):
Vous pouvez également convertir l'inverse:
Pour lire une chaîne dans un flux en utilisant exactement ce que java fournit.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));