C'è un modo semplice per evitare di affrontare i problemi di codifica del testo?
C'è un modo semplice per evitare di affrontare i problemi di codifica del testo?
Risposte:
Non puoi davvero evitare di affrontare i problemi di codifica del testo, ma ci sono soluzioni esistenti in Apache Commons:
Reader
a InputStream
:ReaderInputStream
Writer
a OutputStream
:WriterOutputStream
Devi solo scegliere la codifica che preferisci.
Se stai iniziando con una stringa puoi anche fare quanto segue:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
ReaderInputStream
implementazione richiederebbe meno memoria: non dovrebbe essere necessario memorizzare tutti i byte in un array contemporaneamente.
Ebbene, un Reader si occupa di caratteri e un InputStream si occupa di byte. La codifica specifica come desideri rappresentare i tuoi caratteri come byte, quindi non puoi davvero ignorare il problema. Per quanto riguarda evitare problemi, la mia opinione è: scegli un set di caratteri (ad esempio "UTF-8") e mantienilo.
Per quanto riguarda come fare in realtà, come è stato sottolineato, " i nomi ovvie per queste classi sono ReaderInputStream e WriterOutputStream . " Sorprendentemente, " questi non sono inclusi nella libreria Java ", anche se le classi 'opposti', InputStreamReader e OutputStreamWriter sono incluso.
Quindi, molte persone hanno escogitato le proprie implementazioni, incluso Apache Commons IO . A seconda dei problemi di licenza, probabilmente sarai in grado di includere la libreria commons-io nel tuo progetto, o anche copiare una parte del codice sorgente (che è scaricabile qui ).
Come puoi vedere, la documentazione di entrambe le classi afferma che "tutte le codifiche dei set di caratteri supportate da JRE sono gestite correttamente".
NB Un commento su una delle altre risposte qui menziona questo bug . Ma ciò influisce sulla classe Apache Ant ReaderInputStream ( qui ), non sulla classe Apache Commons IO ReaderInputStream.
Si noti inoltre che, se si inizia con una stringa, è possibile saltare la creazione di un StringReader e creare un InputStream in un unico passaggio utilizzando org.apache.commons.io.IOUtils da Commons IO in questo modo:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Ovviamente devi ancora pensare alla codifica del testo, ma almeno la conversione avviene in un unico passaggio.
new ByteArrayInputStream(report.toString().getBytes("utf-8"))
, il che implica l'allocazione di due copie aggiuntive del report in memoria. Se il rapporto è grande, è cattivo. Vedi la mia risposta.
Uso:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
In questo modo non è necessaria una conversione anticipata in String
e poi inbyte[]
, che alloca molta più memoria heap, nel caso in cui il report sia di grandi dimensioni. Si converte in byte al volo durante la lettura del flusso, direttamente da StringBuffer.
Utilizza CharSequenceInputStream dal progetto Apache Commons IO.
I nomi ovvi per queste classi sono ReaderInputStream e WriterOutputStream. Purtroppo questi non sono inclusi nella libreria Java. Tuttavia, Google è tuo amico.
Non sono sicuro che risolverà tutti i problemi di codifica del testo, che sono da incubo.
C'è un RFE, ma è chiuso, non verrà risolto.
Non si può evitare di testo codifica problemi, ma commons-io Apache ha
Nota che queste sono le librerie a cui si fa riferimento nella risposta di Peter di koders.com, solo collegamenti alla libreria invece del codice sorgente.
Stai cercando di scrivere il contenuto di a Reader
in un OutputStream
? In tal caso, sarà più facile avvolgere il OutputStream
in un OutputStreamWriter
e scrivere la char
s da Reader
a Writer
, invece di provare a convertire il lettore in 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 avviso quando si utilizza WriterOutputStream: non gestisce sempre la scrittura di dati binari in un file correttamente / lo stesso di un normale flusso di output. Ho avuto un problema con questo che mi ci è voluto del tempo per rintracciarlo.
Se puoi, ti consiglio di utilizzare un flusso di output come base e, se devi scrivere stringhe, utilizza un wrapper OUtputStreamWriter attorno al flusso per farlo. È molto più affidabile convertire il testo in byte rispetto al contrario, motivo per cui WriterOutputStream non fa parte della libreria Java standard
Puoi usare Cactoos (nessun metodo statico, solo oggetti):
Puoi convertire anche al contrario:
Per leggere una stringa in un flusso utilizzando solo ciò che fornisce Java.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));