2010-10-12 170 views
4

我想重置ZipInputStream(即回到开始位置),以便按顺序读取某些文件。我怎么做?我这么stucked ...如何重用/重置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

如果可能的话(即你有一个实际的文件,而不仅仅是一个流从阅读),尽量使用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

'ZipInputStream'是用纯Java编写的一个不同的实现,它不是'ZipFile'的_low-level_。 'ZipFile'使用JNI,不能处理非本地文件。 – 2013-09-22 08:40:43

0

试试这个。它将使用csv处理器处理zip中的每个文件。在我的系统中,输入流是来自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(); 
1

我有同样的问题,我从斑点越来越InputStream和不想使用临时中间文件所以想重置ZipInputStream从ZipInputStream的同一对象再次重读ZipEntries,但我反过来了,这可能会帮助你。

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

我想过这个,但是我担心把所有文件放在内存中的内存负载。任何人都有这个想法? – 2012-11-05 23:24:23

0

其实是没有办法重置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。您现在可以从同一个输入中多次读取。