Ottieni un OutputStream in una stringa


580

Qual è il modo migliore per convogliare l'output da java.io.OutputStream a una stringa in Java?

Di 'che ho il metodo:

  writeToStream(Object o, OutputStream out)

Che scrive determinati dati dall'oggetto nel flusso dato. Tuttavia, voglio ottenere questo output in una stringa il più facilmente possibile.

Sto pensando di scrivere una lezione come questa (non testata):

class StringOutputStream extends OutputStream {

  StringBuilder mBuf;

  public void write(int byte) throws IOException {
    mBuf.append((char) byte);
  }

  public String getString() {
    return mBuf.toString();
  }
}

Ma c'è un modo migliore? Voglio solo eseguire un test!


6
Hai solo byte ASCII? Non hai bisogno di Codepage?
Horcrux7,

In questo caso, si. Comunque, buon punto - non ci avevo pensato.
Adrian Mouat,

Risposte:


607

Vorrei usare a ByteArrayOutputStream. E alla fine puoi chiamare:

new String( baos.toByteArray(), codepage );

o meglio:

baos.toString( codepage );

Per il Stringcostruttore, codepagepuò essere una Stringo un'istanza di java.nio.charset.Charset . Un valore possibile è java.nio.charset.StandardCharsets.UTF_8 .

Il metodo toString()accetta solo un Stringcome un codepageparametro (stand Java 8).


8
ByteArrayOutputStream non ha un metodo toArray (); tuttavia deve toByteArray (). Puoi risolvere la risposta? Inoltre, perché non usare baos.toString (String charsetName) che sarebbe leggermente più semplice.
Jonik,

35
Un bytearray è solo dati binari. Poiché il testo (unicode) può essere codificato binario in molti modi diversi, ByteArrayOutputStream deve sapere quale codifica è stata utilizzata per codificare i byte, quindi può usare la stessa codifica per decodificare nuovamente i byte in una stringa. Semplicemente usare toString senza un argomento non è saggio poiché si ignora il problema invece di affrontarlo; Java utilizzerà la codifica della piattaforma che potrebbe essere corretta ... oppure no. Fondamentalmente è casuale. È necessario scoprire quale codifica è stata utilizzata per scrivere il testo in byte e passare la codifica a String.
Stijn de Witt,

10
Solo un chiarimento sulla tabella codici citata qui: in Java è possibile utilizzare Charset.defaultCharset () o Charset.forName ("set di caratteri specifico"); Ciò che ha funzionato per me è stato: new String (baos.toByteArray (), Charset.defaultCharset ());
Wallace Brown,

7
Usare @WallaceBrown defaultCharsetnon è meglio che ignorare del tutto il set di caratteri - devi scoprire di cosa si tratta prima di usaretoString
artbristol

4
StandardCharsets.UTF_8è un Charset, non un String. Inoltre, il parametro viene chiamato charsetName, non codepage.
OrangeDog

46

Mi piace la libreria IO di Apache Commons. Dai un'occhiata alla sua versione di ByteArrayOutputStream , che ha anche un toString(String enc)metodo toByteArray(). L'uso di componenti esistenti e affidabili come il progetto Commons consente di ridurre e semplificare il codice in modo che sia più piccolo e più facile da estendere e riutilizzare.


10
Salva te stesso un anno della tua vita e leggi tutte le API comuni in modo che quando riscontri un problema, puoi liberare una soluzione completamente testata e di proprietà della comunità.
Bob Herrmann,

15
Sono un avido utente di Apache Commons, ma in questo caso non riesco a capire perché dovresti usare ByteArrayOutputStream di Commons IO invece di java.io.ByteArrayOutputStream di JDK. Quest'ultimo fornisce anche i metodi toString (String charsetName) e toByteArray (). Ti interessa elaborare?
Jonik,

1
Sì, dal momento che il contesto originale era un modo migliore per trasmettere ed estrarre contenuti, ho incluso l'esempio Commons IO poiché includeva un metodo di "scrittura (InputStream)" per un meccanismo allora indefinito / discutibile per popolare OutputStream. Vorrei andare anche con il JDK.
Joe Liversedge,

23

Questo ha funzionato bene

OutputStream output = new OutputStream() {
    private StringBuilder string = new StringBuilder();

    @Override
    public void write(int b) throws IOException {
        this.string.append((char) b );
    }

    //Netbeans IDE automatically overrides this toString()
    public String toString() {
        return this.string.toString();
    }
};

metodo call = >> marshaller.marshal( (Object) toWrite , (OutputStream) output);

quindi per stampare la stringa o ottenerla basta fare riferimento allo stesso flusso "output" Ad esempio, per stampare la stringa su console = >> System.out.println(output);

Cordiali saluti: la mia chiamata al metodo marshaller.marshal(Object,Outputstream)è per lavorare con XML. È irrilevante per questo argomento.

Questo è altamente dispendioso per l'uso produttivo, c'è troppa conversione ed è un po 'lento. Questo è stato appena codificato per dimostrarti che è assolutamente possibile creare un OuputStream personalizzato e generare una stringa. Ma segui Horcrux7 e tutto va bene con solo due chiamate di metodo.

E il mondo vive un altro giorno ...


9
Il semplice cast di un byte in char funzionerà solo su ascii. Usa ByteArrayOutputStream come Horcrux7
Dave Ray l'

2
Concordato con Dave Ray. Non puoi presumere che il tuo byte sia un carattere ASCII. È necessario interpretare i byte utilizzando una codifica. Utilizzare byteArrayOutputStream.toString ("UTF-8") o una nuova stringa (byteArrayOutputStream.toByteArray (), "UTF-8").
Martin Dow,

16

Ecco cosa ho finito per fare:

Obj.writeToStream(toWrite, os);
try {
    String out = new String(os.toByteArray(), "UTF-8");
    assertTrue(out.contains("testString"));
} catch (UnsupportedEncondingException e) {
    fail("Caught exception: " + e.getMessage());
}

Dove os è a ByteArrayOutputStream.


2
@JavaJigs L'ho chiarito in fondo alla mia risposta circa 5 anni fa :)
Adrian Mouat,

19
Valuta di sostituirlo "UTF-8"con StandardCharsets.UTF_8.
james.garriss,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.