2013-04-03 1 views
5

Voglio scrivere su una presa. Da leggere su rete IO, mi sembra che il modo ottimale per scrivere ad esso è quello di fare qualcosa di simile:È eccessivo usare BufferedWriter e BufferedOutputStream insieme?

OutputStream outs=null; 
BufferedWriter out=null; 
out = 
    new BufferedWriter(
    new OutputStreamWriter(new BufferedOutputStream(outs),"UTF-8")); 

Il BufferedWriter sarebbe tamponare l'ingresso al OutputStreamWriter che è raccomandato, in quanto impedisce lo scrittore dall'avvio del codificatore per ogni carattere.

Il BufferedOutputStream memorizza quindi i byte da Writer per evitare di immettere un byte alla volta potenzialmente nella rete.

Sembra un po 'eccessivo, ma sembra che tutto aiuti? grato per qualsiasi aiuto ..

EDIT: Dal javadoc sul OutputStreamWriter:

Ciascuna invocazione di un metodo write() fa sì che il convertitore di codifica da richiamare sul carattere dato (s). I byte risultanti vengono accumulati in un buffer prima di essere scritti nel flusso di output sottostante. La dimensione di questo buffer può essere specificata, ma per impostazione predefinita è abbastanza grande per la maggior parte degli scopi. Si noti che i caratteri passati ai metodi write() non sono bufferizzati.

Per la massima efficienza, prendere in considerazione il wrapping di un OutputStreamWriter all'interno di un BufferedWriter in modo da evitare frequenti invocazioni del convertitore. Ad esempio:

Writer out = new BufferedWriter(new OutputStreamWriter(System.out)); 

risposta

1

Il BufferedWriter sarebbe tamponare l'ingresso al OutputStreamWriter, che è raccomandato poiché impedisce al scrittore avviare il codificatore per ciascun carattere.

Consigliato da chi e in quale contesto? Cosa intendi con "avvio dell'encoder"? Stai scrivendo comunque un singolo personaggio alla volta allo scrittore? (Non sappiamo molto su come si sta utilizzando lo scrittore ... che potrebbe essere importante.)

Il BufferedOutputStream sarebbe poi tamponare il byte dal Writer per evitare di mettere un byte alla volta potenzialmente su il network.

Cosa ti fa pensare che scriverebbe un byte alla volta? Penso che sia improbabile che OutputStreamWriter scriverà un byte alla volta per lo scrittore sottostante, a meno che non si scriva un personaggio alla volta.

Inoltre, mi aspetto che il flusso di output di rete utilizzi qualcosa come Nagle's algorithm per evitare l'invio di pacchetti a byte singolo.

Come sempre con l'ottimizzazione, dovresti farlo in base alle prove ... hai fatto qualche test con e senza questi livelli di buffering?

EDIT: Giusto per chiarire, non sto dicendo che le classi di buffering sono inutili. In alcuni casi sono assolutamente la strada giusta da percorrere. Sto solo dicendo che, come con lo all'ottimizzazione, non dovrebbero essere usati alla cieca. Dovresti considerare ciò che stai cercando di ottimizzare (utilizzo del processore, utilizzo della memoria, utilizzo della rete, ecc.) E misurare.Ci sono molti fattori che contano qui - non ultimo il modello di scrittura. Se stai già scrivendo "chunkily" - scrivendo grandi blocchi di dati sui personaggi - allora i buffer avranno un impatto relativamente scarso. Se in realtà stai scrivendo un singolo personaggio alla volta per lo scrittore, allora sarebbero più significativi.

+0

Grazie per la risposta. Da javadoc su OutputStreamWriter, "Ogni invocazione di un metodo write() causa l'invocazione del convertitore di codifica sul/i carattere/i dato/i. I byte risultanti vengono accumulati in un buffer prima di essere scritti nel flusso di output sottostante. questo buffer può essere specificato, ma per impostazione predefinita è abbastanza grande per la maggior parte degli scopi.Tenuta che i caratteri passati ai metodi write() non sono bufferizzati.Per la massima efficienza, considera l'involucro di un OutputStreamWriter all'interno di un BufferedWriter in modo da evitare frequenti richiami di convertitori ". Offerta intera in OP edit – Bruce

+0

@Bruce: * Considerare *, sicuro. Non è lo stesso di * raccomandare *. Lo testerei. Sarei molto sorpreso di vederlo fare una differenza significativa nella maggior parte dei casi però. –

+0

Grazie per le tue utili risposte. Sì, dovrei provarlo. In realtà è come parte di un test di programmazione che ho fatto per un colloquio, e volevo sapere quale sarebbe stata la soluzione corretta di default, o almeno quella che non era ovviamente sbagliata. – Bruce

7

Lo scopo delle classi Buffered * è di unire piccole operazioni di scrittura in una più grande, riducendo così il numero di chiamate di sistema e aumentando il throughput.

Poiché un BufferedWriter raccoglie già le scritture in un buffer, quindi converte i caratteri nel buffer in un altro buffer e scrive quel buffer nell'OutputStream sottostante in una singola operazione, OutputStream è già invocato con operazioni di scrittura di grandi dimensioni. Pertanto, BufferedOutputStream non trova nulla da combinare ed è semplicemente ridondante.

Per inciso, lo stesso può applicarsi a BufferedWriter: il buffering aiuterà solo se allo scrittore vengono passati solo pochi caratteri alla volta. Se sai che il chiamante scrive solo stringhe enormi, BufferedWriter non troverà nulla da combinare ed è ridondante.

+1

Grazie per la risposta. Ciò chiarisce molto. Penso che mi sia sembrata una cattiva forma escludere il buffering, ma quello che dici ha molto senso .. – Bruce

1

Sì, è eccessivo. Da Javadoc for OutputStreamWriter: "Ogni richiamo di un metodo write() causa l'invocazione del convertitore di codifica sui caratteri specificati, i byte risultanti vengono accumulati in un buffer prima di essere scritti nel flusso di output sottostante.".

+0

@downvoter Stai discutendo con Javadoc qui. Quale parte di esso è sbagliata esattamente? – EJP

+0

(Non sono il downvoter!) Penso che questa sia una risposta perfetta, succinta! È chiaro che con _wrapping_ con un Buffer, ci assicuriamo che l'encoder venga attivato solo quando c'è un accumulo di caratteri e, poiché ha un buffer interno, attiva solo le scritture sottostanti quando il buffer è pieno. – SusanW