ZIP是压缩文件的格式,使用ZIP可以节省空间
java将压缩/解压缩文件的方法都封装在java.util.zip包下,java实现了I/O数据流和网络数据流的单一接口,所以实现起来比较容易。
主要的一些方法有:ZipOutputStram,ZipIutputStram,ZipEntry.
以下实现ZIP压缩:
首先了解ZipOutputStream类,利用这个类可以将文件压缩,主要的方法有:
- putNextEntry(ZipEntry e):开始编写新的ZIP条目,并且将流定位到条目的开头。Entry方法的作用就是可以让文件从这个入口进入ZIP中
- write(byte[] b,int off,int len):将字节数组写入到当前的ZIP条目下
public class MyZip {
private void zip(String ZipFileName,File inputFile) throws IOException {//创建zip方法,其中的参数ZipFileName是压缩后文件,inputFile要压缩的文件。
ZipOutputStream out=new ZipOutputStream(new FileOutputStream(ZipFileName));//创建了输出流,这里ZipOutputStream()的参数是FileOutPutStream的原因是因为ZIP压缩的对象是文件。
zip(out,inputFile,"");//调用zip方法,实现了zip的重载。这次的参数是本方法中定义过的输出流out,要压缩的文件:inputFile以及文件最后的存储目录base
System.out.println("压缩中....");
out.close();
}
private void zip(ZipOutputStream out,File f,String base) throws IOException {//方法重载
if(f.isDirectory()) {//判断要压缩的文件是否是文件夹
File[] fl=f.listFiles();//如果是文件夹就对把该文件夹中的文件的路径以文件数组的形式获得
if(base.length()!=0) {//判断最后要存储的路径是否已存在
out.putNextEntry(new ZipEntry(base+"/"));//如果已经存在,写入此目录的entry
}
for(int i=0;i<fl.length;i++) {//遍历文件数组
zip(out,fl[i],base+fl[i]);//将文件数组中的文件添加到已经创建的ZIP中。
}
}else {
out.putNextEntry(new ZipEntry(base));//如果base为空。那么就创建新的进入点
//创建FileInputStream对象
FileInputStream in=new FileInputStream(f);//创建该输入流的原因是为了后边判断该流是否到达尾部
int b;
System.out.println(base);
while((b=in.read())!=-1) {
out.write(b);//在没有到达尾部的情况下向已经创建的ZIP中添加
}
in.close();//关闭流
}
}
public static void main(String[] args) throws IOException {
MyZip book=new MyZip();
book.zip("E:/hello.zip",new File("E:/hello"));
System.out.println("压缩完成");
}
}
在走完整个流程之后,我弄明白了程序究竟是如何将文件压缩起来的。重点就在
ZipOutputStream out=new ZipOutputStream(new FileOutputStream(ZipFileName));
这里定义输出流的同时,声明了ZipFileName,我们之前提到过ZipFileName是压缩后的文件,程序在这里使用FileOutputStream(ZipFileName)直接创建了一个zip文件,
这样一来之后的添加压缩文件就遍历要压缩的目录将其中的文件添加到ZIP中。但是可以这样添加的前提是在使用Entry方法的前提下,要不然Entry方法存在就毫无意义。
解压缩:
解压缩中主要用到的类是ZipInputStream.该类可以读取ZIP压缩格式的文件,包括已压缩的和未压缩的条目。构造方法是ZipInputStream(InputStream in)
以下解压代码是基于以上压缩代码基础而来:
public class Decompressing {//创建解压类
public static void main(String[] args) {
File file=new File("E:\\hello.zip");//需要被解压的文件
ZipInputStream zin;//创建ZinInputStream对象
try {
ZipFile zipfile=new ZipFile(file);//创建压缩文件对象
zin=new ZipInputStream(new FileInputStream(file));//将要被压缩的文件对象放入zipInputStream中
ZipEntry entry=zin.getNextEntry();//构建出出口,这里跳过了根目录,直接获得了下一个ZipEntry
while((entry=zin.getNextEntry())!=null&&!entry.isDirectory()) {//判断entry是否为空,是否是文件夹
File tmp=new File(entry.getName());//输出文件路径
System.out.println(entry.getName());
if(!tmp.exists()) {//如果文件不存在
tmp.getParentFile().mkdirs();//创建文件父类文件夹路径
OutputStream os=new FileOutputStream(tmp);//将文件目录中的文件放入输出流中,用输出流读取压缩文件中指定目录的文件
InputStream in=zipfile.getInputStream(entry);
int count=0;
while((count=in.read())!=-1) {//如有输入流可以读取到数值
os.write(count);//输出流写入
}
os.close();
in.close();
}
zin.closeEntry();
System.out.println(entry.getName()+"解压成功");
}
zin.close();
} catch (ZipException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
本实例是通过ZipEntry类的getName()方法得知此文件的全称(含path),借此来决定压缩之后的目录和文件名,使用ZipInputStream类来解压文件,必须先使用ZipInputStream类的getNextEntry()方法来取得其内第一个ZipEntry.
完.