GZIPInputStream đọc từng dòng


85

Tôi có một tệp ở định dạng .gz. Lớp java để đọc tệp này là GZIPInputStream. Tuy nhiên, lớp này không mở rộng lớp BufferedReader của java. Do đó, tôi không thể đọc từng dòng tệp. Tôi cần một cái gì đó như thế này

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

Tôi đang tạo lớp của mình để mở rộng lớp Reader hoặc BufferedReader của java và sử dụng GZIPInputStream làm một trong những biến của nó.

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

}

Nhưng, điều này không hoạt động khi tôi sử dụng

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

Ai đó có thể tư vấn làm thế nào để tiếp tục ..


nhìn vào liên kết này stackoverflow.com/q/6717165/779408 . Một phương pháp nén và giải nén được trình bày ở đó.
Bobs

1
Vì tình yêu của tất cả những gì tốt đẹp và đúng đắn trên thế giới này và vì sự tỉnh táo của bất kỳ nhà phát triển nào viết ngay cả những đoạn mã đáng giá từ xa ..... HÃY NHẬN THỨC KÍCH THÍCH ĐIỂM NHƯ @erickson ĐI! Anh ấy là câu trả lời duy nhất chỉ ra điều này, điều này khiến tôi muốn khóc.
James

Câu trả lời:


143

Thiết lập cơ bản của trình trang trí như sau:

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

Vấn đề quan trọng trong đoạn mã này là giá trị của encoding. Đây là mã hóa ký tự của văn bản trong tệp. Có phải là "US-ASCII", "UTF-8", "SHIFT-JIS", "ISO-8859-9",… không? có hàng trăm khả năng và lựa chọn chính xác thường không thể được xác định từ chính tệp. Nó phải được chỉ định thông qua một số kênh ngoài băng tần.

Ví dụ: có thể đó là mặc định của nền tảng. Tuy nhiên, trong môi trường mạng, điều này cực kỳ mong manh. Máy đã viết tệp có thể nằm trong ngăn bên cạnh, nhưng có mã hóa tệp mặc định khác.

Hầu hết các giao thức mạng sử dụng tiêu đề hoặc siêu dữ liệu khác để ghi chú rõ ràng mã hóa ký tự.

Trong trường hợp này, xuất hiện từ phần mở rộng tệp rằng nội dung là XML. XML bao gồm thuộc tính "mã hóa" trong khai báo XML cho mục đích này. Hơn nữa, XML thực sự nên được xử lý bằng trình phân tích cú pháp XML, không phải dưới dạng văn bản. Đọc từng dòng XML có vẻ giống như một trường hợp đặc biệt, mỏng manh.

Không xác định rõ ràng mã hóa là chống lại điều răn thứ hai. Sử dụng mã hóa mặc định khi bạn gặp nguy hiểm!


1
cảm ơn nó đã hoạt động ... Tuy nhiên, không cần đến bước trình đọc .. chúng ta cũng có thể viết nó dưới dạng GZIPInputStream gzip = new GZIPInputStream (new FileInputStream ("F: /gawiki-20090614-stub-meta-history.xml.gz" )); BufferedReader br = new BufferedReader (InputStreamReader mới (gzip));
Kapil D

12
@KapilD làm tôi buồn là bạn đã hoàn toàn bỏ sót quan điểm của anh ấy về bảng mã ... như thể hiện trong nhận xét của bạn và ví dụ trong nhận xét của bạn. Đọc lại câu trả lời của erickson .... có thể hơn 30 lần.
James

Làm thế nào để lệnh gzip biết mã hóa? Tôi muốn đọc nhiều tệp từ rất nhiều máy chủ linux / unix từ khắp nơi trên thế giới ... vì vậy tôi muốn đảm bảo rằng mình làm đúng ... Bài đăng đề cập đến việc mã hóa thường không thể được xác định bởi chính tệp đó ... nhưng lệnh gzip -d dường như hoạt động trên bất kỳ tệp nào mà không có đầu vào riêng biệt ... (nó là những gì tôi sử dụng bây giờ nhưng muốn tránh) vì vậy tôi tìm xem liệu tôi có thể tìm ra cách gzip làm để biết mã hóa không, có thể làm tương tự. Bất kỳ suy nghĩ / đề xuất bất cứ ai có thể chỉ cho tôi đúng hướng?
glyphx

@glyphx Câu hỏi của bạn không rõ ràng. Ý của bạn là làm thế nào bạn có thể nhận ra một tệp gzip khi không có một số xác nhận bên ngoài về loại nội dung? Một gợi ý là phần mở rộng tệp, một gợi ý khác là sự hiện diện của số ma thuật 0x1F8B trong tiêu đề tệp. Tuy nhiên, bạn không thể biết tệp là tệp gzip hợp lệ cho đến khi bạn thực sự xử lý toàn bộ.
erickson

1
Để rõ ràng, tôi biết những tệp này là tệp gzip. Và các tệp được gzipped đều là các tệp dựa trên văn bản, như tệp csv và tệp phân cách bằng đường ống dẫn. Tôi chỉ muốn có thể đọc các tệp này trực tiếp bằng java từng dòng một. Tôi có thể gzip -d chúng và sau đó đọc chúng từng dòng một. Tôi chỉ bối rối trong nhận xét của bạn về việc phải chỉ định mã hóa ... Tôi sẽ nghĩ rằng hầu hết các tệp là ASCII ... nhưng một số có thể có ký tự Châu Á nên có thể là UTF-8? Tôi chỉ muốn đảm bảo rằng tôi làm điều này một cách chính xác ... Điều đó có rõ ràng hơn không? Cảm ơn!
glyphx

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


Câu trả lời của bạn là tuyệt vời. Ngắn gọn và súc tích .. Tuy nhiên, câu trả lời của erickson chi tiết hơn.
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

Bạn có thể sử dụng phương thức sau trong một lớp sử dụng và sử dụng nó bất cứ khi nào cần thiết ...

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

đây là với một dòng

try (BufferedReader br = new BufferedReader(
        new InputStreamReader(
           new GZIPInputStream(
              new FileInputStream(
                 "F:/gawiki-20090614-stub-meta-history.xml.gz"))))) 
     {br.readLine();}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.