Как повторно использовать / сбросить ZipInputStream? - PullRequest
4 голосов
/ 12 октября 2010

Я хочу сбросить ZipInputStream (то есть вернуться в начальную позицию), чтобы прочитать определенные файлы по порядку. Как я могу это сделать? Я так застрял ...

      ZipEntry entry;
        ZipInputStream input = new ZipInputStream(fileStream);//item.getInputStream());

        int check =0;
        while(check!=2){

          entry = input.getNextEntry();
          if(entry.getName().toString().equals("newFile.csv")){
              check =1;
              InputStreamReader inputStreamReader = new InputStreamReader(input);
                reader = new CSVReader(inputStreamReader);
                //read files
                //reset ZipInputStream if file is read.
                }
                reader.close();
          }
            if(entry.getName().toString().equals("anotherFile.csv")){
              check =2;
              InputStreamReader inputStreamReader = new InputStreamReader(input);
                reader = new CSVReader(inputStreamReader);
                //read files
                //reset ZipInputStream if file is read.
                }
                reader.close();
          }

        }

Ответы [ 5 ]

5 голосов
/ 12 октября 2010

Если возможно (т. Е. У вас есть реальный файл, а не просто поток для чтения), попробуйте использовать класс ZipFile , а не более низкоуровневый ZipInputStream.ZipFile заботится о переходе по файлу и открытии потоков для отдельных записей.

ZipFile zip = new ZipFile(filename);
ZipEntry entry = zip.getEntry("newfile.csv");
if (entry != null){
    CSVReader data = new CSVReader(new InputStreamReader(
         zip.getInputStream(entry)));
} 
2 голосов
/ 10 февраля 2017

На самом деле нет способа сбросить ZipInputStream, как вы ожидаете, потому что он не поддерживает сброс / маркеры и т. Д. Но вы можете использовать ByteArrayOutputStream для буферизации InputStream как byte[]

поэтому вы пишете класс, похожий на

private byte[] readStreamBuffer;
private InputStream readStream;

public ZipClass(InputStream readStream){
   this.readStream = readStream;
}

и openReadStream -метод, подобный этому:

private ZipInputStream openReadStream(){
    if (readStreamBuffer == null) {
         //If there was no buffered data yet it will do some new
         ByteArrayOutputStream readStreamBufferStream = new ByteArrayOutputStream();
         try {
            int read = 0;
            byte[] buff = new byte[1024];
            while ((read = zipFileInput.read(buff)) != -1) {
               readStreamBufferStream.write(buff, 0, read);
            }
            readStreamBuffer = readStreamBufferStream.toByteArray();
         }
         finally {
            readStreamBufferStream.flush();
            readStreamBufferStream.close();
         }
      }
   //Read from you new buffered stream data
   readStream = new ByteArrayInputStream(readStreamBuffer);

   //open new ZipInputStream
   return new ZipInputStream(readStream);
}

Теперь вы можете прочитать запись и затем закрыть ее. Если вы позвоните по номеру openReadStream, он предоставит вам новый ZipInputStream, поэтому вы можете выборочно читать записи, подобные этой:

public InputStream read(String entry){
  ZipInputStream unzipStream = openReadStream();
  try {
     return readZipEntry(unzipStream, entryName);
  }
  finally {
     unzipStream.close(); //This closes the zipinputstream
  }
}

вызов метода readZipEntry

private InputStream readZipEntry(ZipInputStream zis, String entry) throws IOException {
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  try {
     // get the zipped file list entry
     try {
        ZipEntry ze = zis.getNextEntry();

        while (ze != null) {
           if (!ze.isDirectory() && ze.getName().equals(entry)) {
              int len;
              byte[] buffer = new byte[BUFFER];
              while ((len = zis.read(buffer)) > 0) {
                 out.write(buffer, 0, len);
              }
              break;
           }
           ze = zis.getNextEntry();
        }
     }
     finally {
        zis.closeEntry();
     }
     InputStream is = new ByteArrayInputStream(out.toByteArray());
     return is;
  }
  finally {
     out.close();
  }
}

И вы получите новый InputStream. Теперь вы можете читать несколько раз с одного и того же входа.

1 голос
/ 19 апреля 2012

У меня та же проблема, я получаю InputStream от Blob и не хочу использовать временные промежуточные файлы, поэтому хочу сбросить ZipInputStream для повторного чтения ZipEntries из того же объекта ZipInputStream, но я получил это иначе, это может помочь тебе.

ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
ZipEntry ze = null;
Map<String, byte[]> fileEntries = new HashMap<String, byte[]>();

while ((ze = zis.getNextEntry()) != null) {

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int count;

    while ((count = zis.read(buffer)) != -1) {
        baos.write(buffer, 0, count);
    }

    String filename = ze.getName();
    byte[] bytes = baos.toByteArray();                    
    fileEntries.put(filename, bytes);
}
//do what ever with the map of fileEntries

Пожалуйста, поделитесь, если у кого-нибудь есть хорошее решение, спасибо

0 голосов
/ 29 октября 2018

Вы можете обернуть InputStream в BufferedInputStream и вызвать методы mark () и reset (), например, так:

BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
bufferedInputStream.mark(100);
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream);

    any operation with zipInputStream ...

bufferedInputStream.reset();

readLimit, который вы передаете методу метода, должен быть достаточно большим, чтобы охватить все операции чтения, которые вы выполняете с помощью inputStream. Если вы установите максимальный предполагаемый размер файла, который вы можете иметь при вводе, вы должны быть защищены.

0 голосов
/ 18 февраля 2012

Попробуй это. Он будет обрабатывать каждый файл в zip-памяти с помощью процессора CSV. В моей системе входной поток является потоком из HTTP-соединения.

// Get the files inside the zip.
ZipInputStream zin = new ZipInputStream(inputStream);
ZipEntry zentry;
while((zentry = zin.getNextEntry()) != null) {
    String fileName = zentry.getName();
    long fileLength = zentry.getSize();
    System.out.println("fileName:: " + fileName + ", " + fileLength);

    // csv parse it.
    int numLines = 0;
    CSVReader fileReader = new CSVReader(new InputStreamReader(zin));
    String[] nextLine;
    while ( (nextLine = fileReader.readNext()) != null) {
        numLines++;
    }
    zin.closeEntry();

    System.out.println("    number of lines: " + numLines);
}
zin.close();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...