用J2se的java.util.jar进行jar文件的解压

由于需要做一个在线更新模块,需要在程序里对jar文件解压,测试程序如下
开始的测试程序如下:

package test;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.*;

public class TestJarFile extends Thread {



/**
* @param args
*/
public TestJarFile(){
run();
}
public void UnJarFile(){
JarFile xJarFile = null;
JarEntry xJarEntry;
Enumeration<JarEntry> enumer;
BufferedInputStream is = null;
FileOutputStream fos = null;
byte data[] = new byte[1024];
try {
xJarFile=new JarFile("d:/TestJar.jar");
if(xJarFile.size()==0) return;

enumer=xJarFile.entries();

[color=red]
while(enumer.hasMoreElements()){
xJarEntry= enumer.nextElement();
if(xJarEntry.isDirectory()){
//event
continue;
}
is=new BufferedInputStream(xJarFile.getInputStream(xJarEntry));
System.out.println(xJarEntry.getName());
if(xJarEntry.getName().contains(".MF")) continue;
fos =new FileOutputStream("D:/TestJar/"+xJarEntry.getName());
int len=0;
[/color]
while((len=is.read(data))!=-1){

fos.write(data,0,len);

}
}



} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try{
[color=greens]
fos.flush();
fos.close();
is.close();
[/color]
}
catch(Exception e){

}
}

}
public static void main(String[] args) {
TestJarFile t=new TestJarFile();


}
public void run(){
File xDir=new File("D:/TestJar/");
long count=9999999l;
while(true){
try {
sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

File xFiles[]=xDir.listFiles();
System.out.println(xFiles.length);
if(xFiles.length==0){

UnJarFile();
}
}



}

}



发现确实可以解压,但被解压的jar文件一直被线程占用,不能删除,后来经javaworld版大指点发现问题:
红色部分,每次循环都生成一个input/output stream,但我在finally里(绿色)只处理了最后一个stream的close,导致之前的stream全部没有清除。
解决办法是加上xJarFile.close(),就可以了。
但是,新问题又来了,虽然被解压的jar包不被线程占用了,但是解出来的文件夹里的文件却被线程占用(解出来的文件),当用完后不能删除。最后怀疑是没有做垃圾回收导致的问题所以在finally里又加上System.gc()这个方法。但这个方法只是标明可以进行垃圾回收,到底回收不回收却用jvm决定,所以并不知道是否安全。
最后发现使用JarFile.close()并不能关闭输出流 doc上写的是“将关闭以前调用 getInputStream 方法返回的所有输入流。”,输出流还是需要手动清除,System.gc()其实就是代替你清除这些没有回收的内存,为了安全起见改成手动.

[code]
package test;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.*;

public class TestJarFile extends Thread {



/**
* @param args
*/
public TestJarFile(){
run();
}
public void UnJarFile(){
JarFile xJarFile = null;
JarEntry xJarEntry;
Enumeration<JarEntry> enumer;
BufferedInputStream is = null;
FileOutputStream fos = null;
byte data[] = new byte[1024];
try {
xJarFile=new JarFile("d:/TestJar.jar");
if(xJarFile.size()==0) return;

enumer=xJarFile.entries();

while(enumer.hasMoreElements()){
xJarEntry= enumer.nextElement();
if(xJarEntry.isDirectory()) continue;
is=new BufferedInputStream(xJarFile.getInputStream(xJarEntry));
System.out.println(xJarEntry.getName());
if(xJarEntry.getName().contains(".MF")) continue;
fos =new FileOutputStream("D:/TestJar/"+xJarEntry.getName());
int len=0;
while((len=is.read(data))!=-1){

fos.write(data,0,len);

}
fos.flush();
fos.close();
fos=null;

}




} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try{
fos.flush();
fos.close();
xJarFile.close();
is.close();
// System.gc();

}
catch(Exception e){

}
}

}
public static void main(String[] args) {
TestJarFile t=new TestJarFile();


}
public void run(){
File xDir=new File("D:/TestJar/");
while(true){
try {
sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

File xFiles[]=xDir.listFiles();
System.out.println(xFiles.length);
if(xFiles.length==0){
UnJarFile();
}
}



}

}

在第一个while循环里当用完output stream后就立刻清空。最后问题的症结还是在于outputstream的对象没有释放导致的问题发生

[/code]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值