GZIPInputStream อ่านทีละบรรทัด


85

ฉันมีไฟล์ในรูปแบบ. gz คลาส java สำหรับอ่านไฟล์นี้คือ GZIPInputStream อย่างไรก็ตามคลาสนี้ไม่ได้ขยายคลาส BufferedReader ของ java ด้วยเหตุนี้ฉันจึงไม่สามารถอ่านไฟล์ทีละบรรทัดได้ ฉันต้องการอะไรแบบนี้

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

ฉันแม้ว่าจะสร้างคลาสของฉันซึ่งขยายคลาส Reader หรือ BufferedReader ของ java และใช้ 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 วิธีการบีบอัดและคลายการบีบอัดจะแสดงอยู่ที่นั่น
บ็อบ

1
สำหรับความรักของทุกสิ่งที่ดีและถูกต้องในโลกนี้และเพื่อความมีสติของนักพัฒนาทุกคนที่เขียนโค้ดที่คุ้มค่าจากระยะไกล ..... ระวังการเข้ารหัส AS @erickson POINTS OUT! เขาเป็นคำตอบเดียวที่ชี้ให้เห็นสิ่งนี้ซึ่งทำให้ฉันอยากจะร้องไห้
James

คำตอบ:


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 สำหรับวัตถุประสงค์นี้ นอกจากนี้ XML ควรได้รับการประมวลผลด้วยตัวแยกวิเคราะห์ XML ไม่ใช่เป็นข้อความ การอ่าน XML ทีละบรรทัดดูเหมือนจะเป็นกรณีพิเศษที่เปราะบาง

การไม่ระบุการเข้ารหัสอย่างชัดเจนถือเป็นการขัดต่อบัญญัติที่สอง ใช้การเข้ารหัสเริ่มต้นที่อันตรายของคุณ!


1
ขอบคุณที่ใช้งานได้ ... อย่างไรก็ตามไม่จำเป็นต้องอ่านขั้นตอน .. เราสามารถเขียนเป็น GZIPInputStream gzip = GZIPInputStream ใหม่ (FileInputStream ใหม่ ("F: /gawiki-20090614-stub-meta-history.xml.gz" )); BufferedReader br = BufferedReader ใหม่ (InputStreamReader ใหม่ (gzip));
Kapil D

12
@KapilD ทำให้ฉันเสียใจที่คุณพลาดประเด็นของเขาเกี่ยวกับการเข้ารหัส ... ดังที่แสดงในความคิดเห็นของคุณและตัวอย่างในความคิดเห็นของคุณ อ่านคำตอบของ erickson อีกครั้ง .... อาจจะเกิน 30 ครั้ง
James

คำสั่ง gzip รู้การเข้ารหัสได้อย่างไร ฉันต้องการอ่านไฟล์จำนวนมากจากเซิร์ฟเวอร์ linux / unix จำนวนมากจากทั่วทุกมุมโลก ... ดังนั้นฉันต้องการให้แน่ใจว่าฉันทำถูกต้อง ... โพสต์กล่าวถึงการเข้ารหัสมักไม่สามารถกำหนดได้ด้วยตัวไฟล์เอง ... แต่ดูเหมือนว่าคำสั่ง gzip -d จะทำงานกับไฟล์ใด ๆ ที่ไม่มีอินพุตแยกต่างหาก ... (เป็นสิ่งที่ฉันใช้ตอนนี้ แต่ต้องการหลีกเลี่ยง) ดังนั้นฉันจึงคิดว่าฉันสามารถหาว่า gzip รู้การเข้ารหัสได้หรือไม่ สามารถทำได้เช่นเดียวกัน ความคิด / ข้อเสนอแนะใด ๆ ที่ใครสามารถชี้ให้ฉันไปในทิศทางที่ถูกต้อง?
สัญลักษณ์

@glyphx คำถามของคุณไม่ชัดเจน คุณหมายถึงวิธีการจดจำไฟล์ gzip ในกรณีที่ไม่มีการยืนยันภายนอกเกี่ยวกับประเภทเนื้อหาหรือไม่ คำใบ้อย่างหนึ่งคือนามสกุลไฟล์อีกคำหนึ่งคือการมีหมายเลขมายากล 0x1F8B ในส่วนหัวของไฟล์ อย่างไรก็ตามคุณไม่สามารถรู้ได้ว่าไฟล์นั้นเป็นไฟล์ gzip ที่ถูกต้องจนกว่าคุณจะประมวลผลทั้งหมดจริงๆ
erickson

1
เพื่อความชัดเจนฉันรู้ว่าไฟล์เหล่านี้เป็นไฟล์ gzip และไฟล์ gzipped เป็นไฟล์ข้อความทั้งหมดเช่นไฟล์ csv และไปป์ ฉันแค่อยากจะสามารถอ่านไฟล์เหล่านี้โดยตรงด้วย java ทีละบรรทัด ฉันสามารถ gzip -d แล้วอ่านทีละบรรทัดได้ไม่มีปัญหา ฉันสับสนในความคิดเห็นของคุณเกี่ยวกับการต้องระบุการเข้ารหัส ... ฉันคิดว่าไฟล์ส่วนใหญ่เป็น ASCII ... แต่บางไฟล์อาจมีอักขระเอเชียดังนั้นอาจเป็น UTF-8? ฉันแค่อยากให้แน่ใจว่าฉันทำถูกต้อง ... ชัดเจนกว่านี้ไหม? ขอบคุณ!
ร่ายมนตร์

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


คำตอบของคุณดีมาก สั้นและกระชับ .. อย่างไรก็ตามคำตอบของ erickson มีรายละเอียดมากกว่านี้
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

นี่คือหนึ่งบรรทัด

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.