GZIPInputStream построчное чтение

85

У меня есть файл в формате .gz. Класс Java для чтения этого файла - GZIPInputStream. Однако этот класс не расширяет класс BufferedReader для java. В результате я не могу читать файл построчно. Мне нужно что-то вроде этого

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 . Здесь представлен метод сжатия и распаковки.
Bobs
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 атрибут "кодировка". Более того, XML действительно следует обрабатывать с помощью анализатора XML, а не как текст. Построчное чтение XML кажется хрупким, частным случаем.

Отсутствие явного указания кодировки противоречит второй заповеди. Используйте кодировку по умолчанию на свой страх и риск!

Эриксон
источник
1
спасибо, это сработало ... Однако нет необходимости в шаге чтения ... мы также можем записать его как GZIPInputStream gzip = new GZIPInputStream (new FileInputStream ("F: /gawiki-20090614-stub-meta-history.xml.gz" )); BufferedReader br = новый BufferedReader (новый InputStreamReader (gzip));
Kapil D
12
@KapilD, мне грустно, что вы полностью упустили его точку зрения о кодировке ... как показано в вашем комментарии и примере в вашем комментарии. Перечитайте ответ Эриксона ... может быть, 30 раз.
Джеймс
Как команда gzip узнает кодировку? Я хочу прочитать много файлов с множества серверов linux / unix со всего мира ... поэтому я хочу убедиться, что делаю это правильно ... В сообщении упоминается, что кодировка обычно не может быть определена самим файлом ... но команда gzip -d, похоже, работает с любым файлом без отдельного ввода ... (это то, что я использую сейчас, но хочу обойти), поэтому я полагаю, могу ли я просто выяснить, что делает gzip, чтобы узнать кодировку, я может сделать то же самое. Любые мысли / предложения, может ли кто-нибудь указать мне в правильном направлении?
глиф
@glyphx Ваш вопрос непонятен. Вы имеете в виду, как можно распознать файл gzip при отсутствии какого-либо внешнего утверждения о типе содержимого? Один намек - это расширение файла, другой - наличие магического числа 0x1F8B в заголовке файла. Однако вы не можете узнать, является ли файл допустимым файлом gzip, пока не обработаете его целиком.
erickson
1
Для ясности, я знаю, что это файлы gzip. А сжатые файлы - это все текстовые файлы, такие как файлы 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();

ЧссПлы76
источник
Ваш ответ отличный. Кратко и лаконично ... Однако ответ Эриксона более подробен.
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;
}
Memin
источник
1

вот с одной строкой

try (BufferedReader br = new BufferedReader(
        new InputStreamReader(
           new GZIPInputStream(
              new FileInputStream(
                 "F:/gawiki-20090614-stub-meta-history.xml.gz"))))) 
     {br.readLine();}
Укротитель
источник