GZIPInputStreamは1行ずつ読み取ります


85

.gz形式のファイルがあります。このファイルを読み取るためのJavaクラスはGZIPInputStreamです。ただし、このクラスはjavaのBufferedReaderクラスを拡張しません。その結果、ファイルを1行ずつ読み取ることができません。私はこのようなものが必要です

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

JavaのReaderまたはBufferedReaderクラスを拡張し、その変数の1つとしてGZIPInputStreamを使用するクラスを作成することを考えました。

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);
    }

}

しかし、これは私が使用すると機能しません

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

誰かがどのように進めるかアドバイスできますか..


このリンクstackoverflow.com/q/6717165/779408を見てください。そこには、圧縮と解凍の方法が示されています。
ボブス2013年

1
この世界で善良で正しいものすべてを愛し、リモートで価値のあるコードを書く開発者の正気のために..... @ ericksonが指摘するようにエンコードすることに注意してください!これを指摘するのは彼だけで、泣きたいです。
ジェームズ

回答:


143

デコレータの基本的な設定は次のとおりです。

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

このスニペットの重要な問題は、の値ですencoding。これは、ファイル内のテキストの文字エンコードです。「US-ASCII」、「UTF-8」、「SHIFT-JIS」、「ISO-8859-9」、…?何百もの可能性があり、通常、ファイル自体から正しい選択を決定することはできません。帯域外チャネルを介して指定する必要があります。

たとえば、プラットフォームのデフォルトかもしれません。ただし、ネットワーク環境では、これは非常に脆弱です。ファイルを書き込んだマシンは隣接するキュービクルにある可能性がありますが、デフォルトのファイルエンコーディングが異なります。

ほとんどのネットワークプロトコルは、ヘッダーまたはその他のメタデータを使用して、文字エンコードを明示的に記録します。

この場合、ファイル拡張子から、コンテンツはXMLであるように見えます。XMLには、この目的のためにXML宣言に「encoding」属性が含まれています。さらに、XMLは、テキストとしてではなく、XMLパーサーを使用して実際に処理する必要があります。XMLを1行ずつ読み取ることは、壊れやすい特殊なケースのように思われます。

エンコーディングを明示的に指定しないことは、2番目の戒めに反し ます危険にさらされているデフォルトのエンコーディングを使用してください!


1
動作してくれてありがとう...しかし、リーダーステップは必要ありません..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コメントとコメントの例に示されているように、エンコーディングに関する彼の主張を完全に見逃してしまったのは悲しいことです。エリクソンの答えを読み直してください....多分30回以上。
ジェームズ

gzipコマンドはどのようにエンコーディングを認識しますか?世界中の多くのlinux / unixサーバーから多くのファイルを読みたいので、これを正しく行うようにしたいのですが、エンコードは通常、ファイル自体では判別できないと投稿されています。 ...しかし、gzip -dコマンドは、個別の入力がなくてもすべてのファイルで機能するようです...(現在使用しているものですが回避したい)ので、gzipがエンコーディングを知るために何をするのかを理解できるかどうかを判断します。同じことができます。誰かが私を正しい方向に向けることができる考え/提案はありますか?
glyphx 2013

@glyphxあなたの質問は明確ではありません。コンテンツタイプに関する外部アサーションがない場合に、gzipファイルをどのように認識できるのでしょうか。1つのヒントはファイル拡張子であり、もう1つはファイルヘッダーにマジックナンバー0x1F8Bが存在することです。ただし、実際にすべてを処理するまで、ファイルが有効なgzipファイルであるかどうかはわかりません。
エリクソン2013

1
明確にするために、私はこれらのファイルがgzipファイルであることを知っています。また、gzipで圧縮されたファイルは、csvファイルやパイプ区切りファイルなどのすべてのテキストベースのファイルです。これらのファイルをJavaで1行ずつ直接読み取れるようにしたいだけです。それらをgzip-dしてから、問題なく1行ずつ読み取ることができます。エンコーディングを指定する必要があるというコメントで混乱しました...ほとんどのファイルはASCIIだと思います...しかし、アジアの文字が含まれている可能性があるので、UTF-8でしょうか?私はこれを正しく行うことを確認したいだけです...それはもっと明確ですか?ありがとう!
glyphx 2013

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


あなたの答えは素晴らしいです。短く簡潔な..しかし、エリクソンの答えはより詳細です。
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

utilクラスで次のメソッドを使用して、必要に応じて使用できます...

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

ここに1行あります

try (BufferedReader br = new BufferedReader(
        new InputStreamReader(
           new GZIPInputStream(
              new FileInputStream(
                 "F:/gawiki-20090614-stub-meta-history.xml.gz"))))) 
     {br.readLine();}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.