GZIPInputStream читання рядка за рядком


85

У мене є файл у форматі .gz. Класом Java для читання цього файлу є GZIPInputStream. Однак цей клас не поширює клас Java BufferedReader. Як результат, я не можу прочитати файл по черзі. Мені потрібно щось подібне

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

Я хоч і створив свій клас, який розширює клас Java Reader або BufferedReader і використовую 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
За любов до всього доброго і правильного у цьому світі, а також за осудність будь-яких розробників, які пишуть навіть віддалено вартий код ..... БУДЬТЕ ВІДОМОСТІ КОДУВАННЯ ЯК ТАК @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 включає атрибут "encoding" у декларацію XML. Крім того, XML слід обробляти за допомогою синтаксичного аналізатора XML, а не як текст. Читання XML по черзі здається крихким, особливим випадком.

Неможливість явно вказати кодування суперечить другій заповіді. Використовуйте кодування за замовчуванням на свій ризик!


1
дякую, це спрацювало ... Однак, немає необхідності в кроці читача .. ми також можемо записати його як GZIPInputStream gzip = new GZIPInputStream (new FileInputStream ("F: /gawiki-20090614-stub-meta-history.xml.gz" )); BufferedReader br = новий BufferedReader (новий InputStreamReader (gzip));
Капіл Д

12
@KapilD мені прикро, що ти повністю пропустив його думку щодо кодування ... як показано у вашому коментарі та прикладі у вашому коментарі. Перечитайте відповідь Еріксона .... можливо 30 разів.
James

Як команда gzip знає кодування? Я хочу прочитати багато файлів з багатьох серверів Linux / Unix з усього світу ... тому я хочу переконатися, що я роблю це правильно ... Кодування згаданих публікацій зазвичай не може бути визначено самим файлом ... але команда gzip -d, здається, працює з будь-яким файлом без окремого введення ... (це те, що я використовую зараз, але хочу обійти), тому я зрозумів, чи можу я просто зрозуміти, що робить gzip, щоб знати кодування, я може зробити те саме. Будь-які думки / пропозиції може хтось направити мене у правильному напрямку?
glyphx

@glyphx Ваше запитання незрозуміле. Ви маєте на увазі, як можна розпізнати файл gzip за відсутності якихось зовнішніх тверджень про тип вмісту? Один підказка - розширення файлу, інший - наявність магічного числа 0x1F8B у заголовку файлу. Однак ви не можете знати, що файл є дійсним файлом gzip, доки фактично не обробите все це.
erickson

1
Щоб бути зрозумілим, я знаю, що ці файли є файлами gzip. А розпаковані файли - це всі текстові файли, такі як файли CSV та pipe delim. Я просто хочу мати можливість читати ці файли безпосередньо за допомогою Java, рядок за рядком. Я можу gzip -d їх, а потім читати їх рядок за рядком, не проблема. Я просто заплутався у ваших коментарях щодо необхідності вказувати кодування ... Я думаю, більшість файлів мають ASCII ... але деякі можуть мати азіатські символи, тож, можливо, UTF-8? Я просто хочу переконатись, що я роблю це правильно ... Це зрозуміліше? Дякую!
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();


Ваша відповідь чудова. Короткий і стислий .. Однак відповідь Еріксона є більш детальною.
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();}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.