2012-06-04 1 views
8

Come posso creare una classe che richiede un impianto di OutputStream e scrive il contenuto su di esso?Come scrivere le stringhe su un OutputStream

Ad esempio, il seguente metodo di stampa è errato e non verrà compilato. Quali sono le opzioni o le tecniche migliori?

public class FooBarPrinter{ 
    private OutputStream o; 
    public FooBarPrinter(OutputStream o){ 
     this.o=o; 
    } 

    public void print(String s){   
     o.write(s); 
    } 
} 
+6

Si dovrebbe 1) guarda l'API OutputStream e usa i metodi disponibili, e 2) se hai un errore, inserisci qui l'errore in modo da non dover indovinare cosa non va. –

+4

Ad esempio, l'API mostrerà che non esiste un metodo OutputStream chiamato write (...) che accetta un parametro String, quindi non è possibile crearne uno e aspettarsi che funzioni. Invece è necessario utilizzare i metodi disponibili. –

risposta

20

Un generico OutputStream non hanno la possibilità di scrivere un String direttamente ad esso. Invece, è necessario ottenere lo byte[] del String e quindi scriverlo nello stream.

public void print(String s){ 
    o.write(s.getBytes()); 
} 

fare riferimento alla documentazione OutputStream java per ulteriori informazioni sui tipi di dati supportati in scrittura.

Il mio suggerimento per migliorarlo è assicurarsi che lo OutputStream fornito nel costruttore sia un BufferedOutputStream, in quanto ciò migliorerà le prestazioni del codice. Funziona tramite il buffering di alcuni dati in memoria e la scrittura su disco in grossi pezzi invece di molte scritture più piccole.

Ecco la documentazione java per BufferedOutputStream

0

Per scrivere stringhe, date un'occhiata alla classe PrintStream. Puoi vedere un esempio di una classe che fa ciò che intendi here.

Inoltre, si può avvolgere un OutputStream utilizzando one of the PrintStream constructors:

public class FooBarPrinter{ 
    private PrintStream p; 
    public FooBarPrinter(OutputStream o){ 
    p = new PrintStream(o); 
    } 
    public void print(String s){  
    p.print(s); 
    } 
} 

EDIT: si noti che è possibile anche utilizzare la classe PrintWriter nello stesso modo PrintStream sopra; che in genere è migliore perché è possibile specificare la codifica da utilizzare, evitando qualsiasi dipendenza dalla piattaforma.

+2

Va notato che 'PrintStream' gestisce le eccezioni in modo diverso: *" A differenza di altri flussi di output, un 'PrintStream' non getta mai una' IOException', invece, situazioni eccezionali impostano semplicemente un flag interno che può essere testato tramite 'checkError () 'metodo." * –

+0

@GregKopff: Sì, ora è noto. Grazie! –

9

Penso che alle altre risposte manchi un punto/domanda importante.

si deve essere molto usare un OutputStream?

Le gerarchie di classi OutputStream e InputStream sono per la scrittura e la lettura di dati orientati ai byte. Ma le stringhe Java non sono orientate ai byte. Sono orientati ai caratteri (in prima approssimazione) e i caratteri in Java sono unità di codice Unicode a 16 bit.

Quando si scrivono i caratteri su un flusso di byte, la JVM deve eseguire una conversione in codificare i caratteri come byte. In effetti, ci sono molti modi possibili per farlo. Ad esempio, UTF-8 codificherà ciascun carattere nella sequenza come uno o più byte, Latin-1 o ASCII codificherà un sottoinsieme di caratteri come byte singoli e trasformerà gli altri in (probabilmente) punti interrogativi. E così via.

Ora, è possibile scrivere qualcosa del genere:

public void print(String s){ 
     o.write(s.getBytes()); 
    } 

ma ha un problema.Il problema è che il metodo getBytes() su un String utilizza lo schema di codifica dei caratteri predefinito della JVM per eseguire la conversione. E questo (lo schema di codifica predefinito) dipende dall'ambiente in cui è stata lanciata la JVM. Quindi quel codice, fa cose diverse a seconda dell'ambiente. Ora si potrebbe rimediare specificando il charset:

public void print(String s){ 
     o.write(s.getBytes("UTF-8")); 
    } 

ma che diventa ingombrante se si sta chiamando getBytes in un sacco di posti.

Se si sta eseguendo un sacco di output basato su testo, un'idea migliore è utilizzare l'API Writer anziché l'API OutputStream. L'API Writer e le sue implementazioni riguardano la conversione sotto il cofano ... e in modo più coerente ed efficiente.

Il punto finale è che ci sono altre API che possono essere utili nel fare l'output basato sul testo.

  • L'uscita di sostegno efficiente BufferedWriter classe (e anche BufferedOutputStream) introducendo buffer in memoria nel processo di uscita. Ciò consente di risparmiare chiamate di sistema, soprattutto se si eseguono molte piccole operazioni di scrittura.
  • La classe PrintWriter fornisce un sacco di metodi di convenienza e rimuove anche la necessità di gestire IOExceptions. (In caso di IOException, il PrintWriter fa una nota di esso. C'è un metodo per testare se si è verificata un'eccezione. Questo può essere utile o pericolose, a seconda di quello che stai facendo ...)