Come convertire un Reader in InputStream e uno Writer in OutputStream?
Domanda
Esiste un modo semplice per evitare di affrontare problemi di codifica del testo?
Soluzione
Non puoi davvero evitare di affrontare i problemi di codifica del testo, ma esistono soluzioni esistenti:
Reader
AInputStream
:ReaderInputStream
Writer
AOutputStream
:WriterOutputStream
Devi solo scegliere la codifica che preferisci.
Altri suggerimenti
Se stai iniziando con una stringa puoi anche fare quanto segue:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
Bene, un Reader si occupa dei caratteri e un InputStream si occupa dei 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 es."UTF-8") e mantienilo.
Per quanto riguarda come farlo effettivamente, come è stato sottolineato, "i nomi ovvi per queste classi sono ReaderInputStream E WriterOutputStream." Sorprendentemente "questi non sono inclusi nella libreria Java"anche se le classi 'opposte', InputStreamReader E OutputStreamWriter Sono incluso.
Quindi, molte persone hanno escogitato le proprie implementazioni, incluso Apache Comuni 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).
- Apache ReaderInputStream: API / collegamento diretto al codice sorgente
- Apache WriterOutputStream: API / collegamento diretto al codice sorgente
Come puoi vedere, la documentazione di entrambe le classi afferma che "tutte le codifiche dei set di caratteri supportate da JRE sono gestite correttamente".
N.B.Un commento su una delle altre risposte qui menziona questo bug.Ma questo riguarda l'Apache Formica Classe ReaderInputStream (Qui), non gli Apache Comuni IO Classe ReaderInputStream.
Tieni inoltre presente che, se stai iniziando con una String, puoi saltare la creazione di uno StringReader e creare un InputStream in un solo passaggio utilizzando org.apache.commons.io.IOUtils da Comuni IO così:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Ovviamente devi ancora pensare alla codifica del testo, ma almeno la conversione avviene in un unico passaggio.
Utilizzo:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
In questo modo non è necessaria una conversione anticipata a String
e poi a byte[]
, che alloca molta più memoria heap, nel caso in cui il report sia di grandi dimensioni.Si converte in byte al volo mentre il flusso viene letto, direttamente da StringBuffer.
Utilizza CharSequenceInputStream dal progetto Apache Commons IO.
I nomi ovvi per queste classi sono ReaderInputStream e WriterOutputStream.Sfortunatamente 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'è una RFE, ma è chiuso, non risolverà il problema.
Non puoi evitare problemi di codifica del testo, ma Apache commons-io ha
Nota che queste sono le librerie a cui fa riferimento la risposta di Peter su koders.com, solo collegamenti alla libreria anziché al codice sorgente.
Stai cercando di scrivere il contenuto di a Reader
ad OutputStream
?Se è così, ti sarà più facile avvolgere il file OutputStream
in un OutputStreamWriter
e scrivi il char
s dal Reader
al 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 avvertimento quando si utilizza WriterOutputStream: non sempre gestisce correttamente la scrittura di dati binari su un file/come un normale flusso di output.Ho avuto un problema con questo che mi ci è voluto un po' per rintracciarlo.
Se puoi, ti consiglio di utilizzare un flusso di output come base e, se hai bisogno di scrivere stringhe, usa 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 Cattoo (nessun metodo statico, solo oggetti):
Puoi anche convertire il contrario:
Per leggere una stringa in un flusso utilizzando esattamente ciò che Java fornisce.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));