Читатель для получения текстовых строк из заархивированного текстового файла

Вывод: Имея байтовое изображение a.zip, содержащее a.txt, как мне получить чистую и правильную программу чтения, которая возвращает строки текстового файла?

Я загружаю образ zip-файла с веб-службы в папку byte[] content. Я хотел бы написать метод, например

private BufferedReader contentToBufferedReader(byte[] content)

который вернет читатель, который можно использовать как

reader = contentToBufferedReader(content);
while ((line = reader.readLine()) != null) {
    processThe(line);
}
reader.close()

На данный момент у меня есть (обновлено)

private BufferedReader contentToBufferedReader(byte[] content) {

    ByteArrayInputStream bais = new ByteArrayInputStream(content);
    ZipInputStream zipStream = new ZipInputStream(bais);
    BufferedReader reader = null;

    try {
        ZipEntry entry = zipStream.getNextEntry();

        // I need only the first (and the only) entry from the zip file.
        if (entry != null) {
            reader = new BufferedReader(new InputStreamReader(zipStream, "UTF-8"));
            System.out.println("contentToBufferedReader(): success");
        }
    }
    catch (IOException e) {
        System.out.println("contentToBufferedReader(): failed...");
        System.out.println(e.getMessage());
    }

    return reader;
}

Я не уверен, как закрыть весь объект потока, когда что-то не получается. Более того, я не уверен, как их закрыть, если reader был успешно возвращен, использован и закрыт.


person pepr    schedule 08.10.2013    source источник
comment
возможный дубликат Чтение текстовых файлов в zip-архиве   -  person Modus Tollens    schedule 08.10.2013
comment
Спасибо, Катя, за подсказку, как украсить zipStream. Я изменил вопрос, чтобы его нельзя было считать дубликатом вопроса, который вы упомянули.   -  person pepr    schedule 08.10.2013


Ответы (2)


Это позволит получить все байты за один раз (для удобства использует guava ByteStreams)

ZipEntry entry = zipStream.getNextEntry();
while (entry != null) {
  if (!entry.isDirectory()) {
    String filename = entry.getName();//this includes the path!
    byte[] data = ByteStreams.toByteArray(zipStream);
    //do something with the bytes 
  }
  entry = zipIn.getNextEntry();
}

вы можете получить ридер следующим образом:

InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(data)));

zipStream продвигается, когда вы вызываете zipStream.getNextEntry(). Я также думаю, что поток не поддерживает отметку и сброс iirc, что означает, что вы можете прочитать его только один раз (следовательно, получить все сразу, прежде чем передавать его другой обработке, которой может потребоваться произвольный доступ)

person tom    schedule 08.10.2013
comment
+1 Спасибо, что научили меня entry.isDirectory(). В противном случае я предпочитаю не извлекать содержимое от zipStream до byte[], если можно этого избежать. Кроме того, я бы предпочел вызывать zipStream.getNextEntry() только в одном месте — в условии while. - person pepr; 08.10.2013
comment
Рад помочь. Обратите внимание, что даже если вы не извлекаете все байты сразу, убедитесь, что вы читаете их только один раз. Мне снились кошмары, когда я это обнаружил. - person tom; 08.10.2013

Проверьте эту тему, вам, вероятно, потребуется сначала разархивировать файл, а затем вы сможете его прочитать.

Какая хорошая библиотека Java для архивирования/распаковки файлов?

person Drake29a    schedule 08.10.2013
comment
+1 за ссылку. Я обнаружил, что zip4j может быть хорошей альтернативой стандартной поддержке zip в Android. Кажется, что полученный мной zip-образ использует zip64, который не поддерживается файлом ZipInputStream. - person pepr; 08.10.2013