GZIPInputStream lettura riga per riga


85

Ho un file in formato .gz. La classe java per leggere questo file è GZIPInputStream. Tuttavia, questa classe non estende la classe BufferedReader di java. Di conseguenza, non sono in grado di leggere il file riga per riga. Ho bisogno di qualcosa di simile

reader  = new MyGZInputStream( some constructor of GZInputStream) 
reader.readLine()...

Ho pensato di creare la mia classe che estenda la classe Reader o BufferedReader di java e utilizzi GZIPInputStream come una delle sue variabili.

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.util.zip.GZIPInputStream;

public class MyGZFilReader extends Reader {

    private GZIPInputStream gzipInputStream = null;
    char[] buf = new char[1024];

    @Override
    public void close() throws IOException {
        gzipInputStream.close();
    }

    public MyGZFilReader(String filename)
               throws FileNotFoundException, IOException {
        gzipInputStream = new GZIPInputStream(new FileInputStream(filename));
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        // TODO Auto-generated method stub
        return gzipInputStream.read((byte[])buf, off, len);
    }

}

Ma questo non funziona quando lo uso

BufferedReader in = new BufferedReader(
    new MyGZFilReader("F:/gawiki-20090614-stub-meta-history.xml.gz"));
System.out.println(in.readLine());

Qualcuno può consigliare come procedere ..


guarda questo link stackoverflow.com/q/6717165/779408 . Qui è rappresentato un metodo di compressione e decompressione.
Bob

1
Per l'amore di tutto ciò che è buono e giusto in questo mondo e per la sanità mentale di tutti gli sviluppatori che scrivono codici validi anche lontanamente ... ATTENERSI ALLA CODIFICA COME RILEVA @erickson! È l'unica risposta che lo fa notare, il che mi fa venire voglia di piangere.
James,

Risposte:


143

La configurazione di base dei decoratori è così:

InputStream fileStream = new FileInputStream(filename);
InputStream gzipStream = new GZIPInputStream(fileStream);
Reader decoder = new InputStreamReader(gzipStream, encoding);
BufferedReader buffered = new BufferedReader(decoder);

La questione chiave in questo frammento è il valore di encoding. Questa è la codifica dei caratteri del testo nel file. È "US-ASCII", "UTF-8", "SHIFT-JIS", "ISO-8859-9", ...? ci sono centinaia di possibilità e la scelta corretta di solito non può essere determinata dal file stesso. Deve essere specificato tramite qualche canale fuori banda.

Ad esempio, forse è l'impostazione predefinita della piattaforma. In un ambiente di rete, tuttavia, questo è estremamente fragile. La macchina che ha scritto il file potrebbe trovarsi nel cubicolo adiacente, ma avere una codifica file predefinita diversa.

La maggior parte dei protocolli di rete utilizza un'intestazione o altri metadati per annotare esplicitamente la codifica dei caratteri.

In questo caso, dall'estensione del file risulta che il contenuto è XML. XML include l'attributo "codifica" nella dichiarazione XML per questo scopo. Inoltre, XML dovrebbe essere realmente elaborato con un parser XML, non come testo. Leggere l'XML riga per riga sembra un caso fragile e speciale.

Non specificare esplicitamente la codifica è contro il secondo comandamento. Usa la codifica predefinita a tuo rischio e pericolo!


1
grazie ha funzionato ... Tuttavia, non è necessario il passaggio del lettore .. possiamo anche scriverlo come GZIPInputStream gzip = new GZIPInputStream (new FileInputStream ("F: /gawiki-20090614-stub-meta-history.xml.gz" )); BufferedReader br = new BufferedReader (new InputStreamReader (gzip));
Kapil D

12
@KapilD mi rattrista che tu abbia completamente perso il suo punto sulla codifica ... come mostrato dal tuo commento e dall'esempio nel tuo commento. Rileggi la risposta di Erickson ... forse 30 volte.
James,

Come fa il comando gzip a conoscere la codifica? Voglio leggere molti file da molti server Linux / unix da tutto il mondo ... quindi voglio assicurarmi di farlo bene ... Il post menziona la codifica di solito non può essere determinata dal file stesso ... ma il comando gzip -d sembra funzionare su qualsiasi file senza input separato ... (è quello che uso ora ma voglio aggirare) quindi immagino che se riesco a capire cosa fa gzip per conoscere la codifica, io può fare lo stesso. Qualche pensiero / suggerimento qualcuno mi può indirizzare nella giusta direzione?
glifo

@glyphx La tua domanda non è chiara. Intendi come riconoscere un file gzip in assenza di affermazioni esterne sul tipo di contenuto? Un suggerimento è l'estensione del file, un altro è la presenza del numero magico 0x1F8B nell'intestazione del file. Tuttavia, non puoi sapere che un file è un file gzip valido finché non elabori effettivamente l'intera cosa.
erickson

1
Per essere chiari, so che questi file sono file gzip. E i file compressi con gzip sono tutti file basati su testo, come csv e file delim pipe. Voglio solo essere in grado di leggere questi file direttamente con java riga per riga. Posso gzip -d e poi leggerli riga per riga senza problemi. Ero solo confuso nei tuoi commenti sul dover specificare la codifica ... Penso che la maggior parte dei file siano ASCII ... ma alcuni potrebbero avere caratteri asiatici, quindi forse UTF-8? Voglio solo assicurarmi di farlo correttamente ... È più chiaro? Grazie!
glifo

44
GZIPInputStream gzip = new GZIPInputStream(new FileInputStream("F:/gawiki-20090614-stub-meta-history.xml.gz"));
BufferedReader br = new BufferedReader(new InputStreamReader(gzip));
br.readLine();


La tua risposta è ottima. Breve e conciso .. Tuttavia, la risposta di Erickson è più dettagliata.
Kapil D

3
BufferedReader in = new BufferedReader(new InputStreamReader(
        new GZIPInputStream(new FileInputStream("F:/gawiki-20090614-stub-meta-history.xml.gz"))));

String content;

while ((content = in.readLine()) != null)

   System.out.println(content);

2

Puoi usare il seguente metodo in una classe util e usarlo ogni volta che è necessario ...

public static List<String> readLinesFromGZ(String filePath) {
    List<String> lines = new ArrayList<>();
    File file = new File(filePath);

    try (GZIPInputStream gzip = new GZIPInputStream(new FileInputStream(file));
            BufferedReader br = new BufferedReader(new InputStreamReader(gzip));) {
        String line = null;
        while ((line = br.readLine()) != null) {
            lines.add(line);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace(System.err);
    } catch (IOException e) {
        e.printStackTrace(System.err);
    }
    return lines;
}

1

qui è con una riga

try (BufferedReader br = new BufferedReader(
        new InputStreamReader(
           new GZIPInputStream(
              new FileInputStream(
                 "F:/gawiki-20090614-stub-meta-history.xml.gz"))))) 
     {br.readLine();}
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.