Domanda

sono sempre stato un po 'confuso con la quantità di diverse implementazioni IO in Java, e ora che sono completamente bloccato nel mio sviluppo del progetto, mi stava prendendo il mio tempo a leggere su utili cose nel frattempo.

Ho capito che non c'è paragone newbie-friendly (a parte breve spiegazione a API per la classe Writer ) tra le diverse sottoclassi della classe Writer. Così ho pensato di fuoco di distanza la domanda, quali sono quelle diverse sottoclassi buono per?

Per esempio, io di solito uso un FileWriter avvolto con un BufferedWriter per le mie uscite ai file, ma sono sempre stato irritato dal fatto che non v'è alcuna println() come metodo, e si deve usare newLine() ogni seconda linea (per fare il umana output leggibile). PrintWriterhas il metodo println() ma nessun costruttore che supporti aggiungendo però ...

Mi piacerebbe davvero grato se mi potesse dare i vostri due centesimi dalla vostra esperienza, o una guida piacevole / how-to si potrebbe avere inciampato su.

EDIT: Grazie per le risposte a tutti, apprezzo molto l'informazioni trasmesso qui. È un po 'un peccato che il tutto append() ha finito per essere a fuoco, si è limitata significava che come un esempio. La mia domanda era per lo più riferimento alla necessità e l'uso di tutte le diverse implementazioni, che immagino che è stato menzionato in qualche modo in un paio di risposte.

E 'difficile scegliere una risposta accettata, dato che ci sono tre risposte davvero solido, ognuno ha contribuito alla mia comprensione del problema. Sto andando andare con Anon, questa volta come lui ha la minor quantità di rep. punti (presumo che sia nuova sul SO). E '15 risposte, alcune delle quali sono davvero ben formulati, e 0 domande chiesto. Buon contributo direi, e che vale la pena di promuovere.

Detto questo, Colind e Jay forniti anche molto buone risposte, e hanno sottolineato idee interessanti. Soprattutto il commento di Jay su Java avvolgendo automaticamente un BufferedWriter era degno di nota. Grazie ancora ragazzi, davvero apprezzato!

È stato utile?

Soluzione

Le classi java.io generalmente seguono il modello Decorator. Così, mentre PrintWriter non ha il costruttore specifica che si potrebbe desiderare, esso ha un costruttore che prende un altro Writer, in modo da poter fare qualcosa di simile al seguente:

FileOutputStream fos = null;
try
{
    fos = new FileOutputStream("foo.txt");
    PrintWriter out = new PrintWriter(
                          new BufferedWriter(
                              new OutputStreamWriter(fos, "UTF-8")));
    // do what you want to do
    out.flush();
    out.close();
}
finally
{
    // quietly close the FileOutputStream (see Jakarta Commons IOUtils)
}

Come nota utilizzo generale, hai sempre voglia di avvolgere un produttore a basso livello (ad esempio FileWriter o OutputStreamWriter) in una BufferedWriter, per ridurre al minimo le operazioni effettive di IO. Tuttavia, questo significa che è necessario in modo esplicito a filo e chiudere il Writer più esterno, al fine di garantire che tutti i contenuti è scritto.

E poi è necessario chiudere il Writer di basso livello in un blocco finally, per garantire che non perdano le risorse.

Modifica :

Guardando MForster 's risposta mi ha fatto prendere un altro sguardo al API per FileWriter. E ho capito che non ci vuole un set di caratteri esplicita, che è una cosa molto brutta. Così ho modificato il mio frammento di codice per utilizzare un FileOutputStream avvolto da un OutputStreamWriter che richiede un set di caratteri esplicito.

Altri suggerimenti

FileWriter non è generalmente una classe accettabile utilizzare. Non permette di specificare l'Charset da utilizzare per la scrittura, il che significa che si sono bloccati con qualunque sia il set di caratteri di default della piattaforma è in esecuzione sul sembra essere. Inutile dire che, questo rende impossibile utilizzare in modo coerente lo stesso set di caratteri per la lettura e la scrittura di file di testo e può portare a dati danneggiati.

Invece di utilizzare FileWriter, si dovrebbe essere avvolgendo un FileOutputStream in un OutputStreamWriter. OutputStreamWriter non consente di specificare un set di caratteri:

File file = ...
OutputStream fileOut = new FileOutputStream(file);
Writer writer = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));

Per usare PrintWriter con quanto sopra, basta avvolgere la BufferedWriter in un PrintWriter:

PrintWriter printWriter = new PrintWriter(writer);

potrebbero anche semplicemente utilizzare il costruttore PrintWriter che prende un File e il nome di un set di caratteri:

PrintWriter printWriter = new PrintWriter(file, "UTF-8");

Questo funziona bene per la vostra situazione particolare, e in realtà fa la stessa cosa esatta come il codice di cui sopra, ma è bene sapere come costruirlo avvolgendo le varie parti.

Gli altri tipi Writer sono per lo più per gli usi specializzati:

  • StringWriter è solo un Writer che può essere utilizzato per creare un String. CharArrayWriter è lo stesso per char[].
  • PipedWriter per tubazioni ad un PipedReader.

Modifica

ho notato che hai commentato un'altra risposta circa la prolissità della creazione di uno scrittore in questo modo. Nota che ci sono le biblioteche, come Guava che aiutano a ridurre il livello di dettaglio delle operazioni comuni. Prendiamo, per esempio, la scrittura di un String in un file in un determinato set di caratteri. Con Guava si può semplicemente scrivere:

Files.write(text, file, Charsets.UTF_8);

Si può anche creare un BufferedWriter in questo modo:

BufferedWriter writer = Files.newWriter(file, Charsets.UTF_8);

PrintWriter non ha un costruttore che accetta un parametro "append", ma FileWriter fa. E sembra logico per me che è lì che essa appartiene. PrintWriter non sa se si sta scrivendo in un file, una presa di corrente, la console, una stringa, ecc Cosa significherebbe per "accodamento" in scrittura ad una presa?

Quindi il modo giusto di fare quello che vuoi è semplicemente:

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter(myfile, append)));

Interessante nota a margine: se si avvolge un OutputStream in un PrintWriter, Java inserisce automaticamente un BufferedWriter nel mezzo. Ma se si avvolgono uno scrittore in un PrintWriter, non è così. Quindi, non si guadagna nulla dicendo:

PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(myfile))));

Basta lasciare fuori la BufferedWriter e l'OutputStreamWriter, che li ottenete per comunque gratuito. Non ho idea se c'è qualche motivo buono per l'inconsistenza.

E 'vero che non è possibile specificare una codifica dei caratteri in un FileWriter come note Colind. Io non so che che lo rende "inaccettabile". Ho quasi sempre sono perfettamente felice di accettare la codifica di default. Forse, se si sta utilizzando una lingua diversa dall'inglese questo è un problema.

La necessità di avvolgere scrittori o OutputStreams a strati è stata fonte di confusione per me quando ho iniziato ad usare Java. Ma una volta a ottenere il blocco di esso, è un grosso problema. Non vi resta che piegare la tua mente nel quadro di scrittura. Ogni scrittore ha una funzione. Pensate a come, voglio stampare su un file, quindi ho bisogno di avvolgere un FileWriter in un PrintWriter. Oppure, voglio convertire un flusso di output per uno scrittore, quindi ho bisogno di un OutputStreamWriter. Ecc.

O forse semplicemente abituarsi a quelle che si usano per tutto il tempo. Figura fuori una volta e ricordare come hai fatto.

È possibile creare un PrintWriter aggiungendo in questo modo:

OutputStream os = new FileOutputStream("/tmp/out", true);
PrintWriter writer = new PrintWriter(os);

Modifica:. post di Anon ha ragione su entrambi utilizzando un BufferedWriter in mezzo e specificare la codifica

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top