我正在尝试解压缩包含其他zip文件的文件。我的尝试基于以下Java2s代码:http://www.java2s.com/Code/Java/File-Input-Output/LoadresourcefromJarfile.htm。
我唯一的困难是当一个条目本身就是一个Jar文件时,我无法解压缩它而不先将它写入临时文件。
以下是我正在做的事情:
public void load(String jarFileName) throws Exception{
ZipFile zf = new ZipFile(jarFileName);
load(zf.entries(),new FileInputStream(jarFileName),zf.size());
}
public void load(Enumeration<? extends ZipEntry> enumeration, InputStream inputStream, int total) throws Exception {
if(enumeration!=null){
while (enumeration.hasMoreElements()) {
ZipEntry ze = (ZipEntry) enumeration.nextElement();
htSizes.put(ze.getName(), new Integer((int) ze.getSize()));
}
}
BufferedInputStream bis = new BufferedInputStream(inputStream);
ZipInputStream zis = new ZipInputStream(bis);
ZipEntry ze = null;
int retrieved=0;
while ((ze = zis.getNextEntry()) != null) {
if (ze.isDirectory()) {
continue;
}
int size = (int) ze.getSize();
if (size == -1 && htSizes.get(ze.getName())!=null) {
size = ((Integer) htSizes.get(ze.getName())).intValue();
}
if(size==-1)
size=total-retrieved;
retrieved+=size;
byte[] b = new byte[(int) size];
int rb = 0;
int chunk = 0;
while (((int) size - rb) > 0) {
chunk = zis.read(b, rb, (int) size - rb);
if (chunk == -1) {
break;
}
rb += chunk;
}
if(ze.getName().endsWith(".jar")){
File f=File.createTempFile("temp", System.nanoTime()+"");
f.deleteOnExit();
FileOutputStream fos= new FileOutputStream(f);
fos.write(b);
fos.close();
load(f.getAbsolutePath());
}
else htJarContents.put(ze.getName(), b);
}
}
我真正想做的是这个:
public void load(String jarFileName) throws Exception{
ZipFile zf = new ZipFile(jarFileName);
load(zf.entries(),new FileInputStream(jarFileName),zf.size());
}
public void load(Enumeration<? extends ZipEntry> enumeration, InputStream inputStream, int total) throws Exception {
if(enumeration!=null){
while (enumeration.hasMoreElements()) {
ZipEntry ze = (ZipEntry) enumeration.nextElement();
htSizes.put(ze.getName(), new Integer((int) ze.getSize()));
}
}
BufferedInputStream bis = new BufferedInputStream(inputStream);
ZipInputStream zis = new ZipInputStream(bis);
ZipEntry ze = null;
int retrieved=0;
while ((ze = zis.getNextEntry()) != null) {
if (ze.isDirectory()) {
continue;
}
int size = (int) ze.getSize();
if (size == -1 && htSizes.get(ze.getName())!=null) {
size = ((Integer) htSizes.get(ze.getName())).intValue();
}
if(size==-1)
size=total-retrieved;
retrieved+=size;
byte[] b = new byte[(int) size];
int rb = 0;
int chunk = 0;
while (((int) size - rb) > 0) {
chunk = zis.read(b, rb, (int) size - rb);
if (chunk == -1) {
break;
}
rb += chunk;
}
if(ze.getName().endsWith(".jar")){
load(null,new ByteArrayOutputstream(b));
}
else htJarContents.put(ze.getName(), b);
}
}
我所看到的第二个版本是内部罐子中包含的条目的大小信息只有在我首先将这个内部jar写入磁盘时才可用。
有没有办法避免这种情况?
非常感谢, 克劳斯。
答案 0 :(得分:0)
我不确切知道你对你的尺寸做了什么,我认为你让他们真的很困惑。 ZipInputStream.getNextEntry()将流定位在条目的开头。来自http://java.sun.com/javase/6/docs/api/java/util/zip/ZipInputStream.html#getNextEntry()
public ZipEntry getNextEntry()抛出 IOException的
读取下一个ZIP文件 进入和位置流在 入门数据的开头。
所以,以下内容对我有用:
public void process(String filename) throws IOException {
process(filename, new FileInputStream(new File(filename)));
}
private void process(String filename, InputStream inputStream) throws IOException {
ZipInputStream zis = new ZipInputStream(inputStream);
ZipEntry ze = null;
while ((ze = zis.getNextEntry()) != null) {
if (ze.isDirectory()) {
continue;
}
System.out.println(ze.getName() + " " + ze.getSize());
if (ze.getName().endsWith(".jar")) {
long size = ze.getSize();
byte[] b = new byte[(int) size];
int rb = 0;
int chunk = 0;
while (((int) size - rb) > 0) {
chunk = zis.read(b, rb, (int) size - rb);
if (chunk == -1) {
break;
}
rb += chunk;
}
process(ze.getName(), new ByteArrayInputStream(b));
}
}
}