我想重置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();
}
}
答案 0 :(得分: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)));
}
答案 1 :(得分:2)
实际上无法按预期重置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。您现在可以从同一输入中多次读取。
答案 2 :(得分:1)
我有同样的问题,我从Blob获取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
请分享,如果有人有一个好的解决方案,谢谢
答案 3 :(得分: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();
答案 4 :(得分:0)
您可以将InputStream封装在BufferedInputStream中,并调用方法mark()和reset(),如下所示:
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
bufferedInputStream.mark(100);
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream);
any operation with zipInputStream ...
bufferedInputStream.reset();
您传递给mark方法的readLimit必须足够大,以覆盖您对inputStream进行的所有读取操作。如果将其设置为输入中可以假定的最大文件大小,则应包括在内。