写在前面:
因本人水平较低,进行代码编写时也是根据CSDN上大佬们的代码,参考编写的,所以,侵删,侵删。。
环境介绍
使用的是JDK1.8,IDEA编辑器
压缩流程及代码
通过获得源文件路径,和要压缩到的目地路径(这里如果不传参数,默认当前目录下),对文件进行判断是文件还是文件夹,是文件就调用压缩方法,进行压缩,文件夹就调用文件夹递归方法,递归到文件时调用压缩方法。
接下来上代码:
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Zipfile {
public Zipfile() {
}
//单文件夹或者单文件
/**
* 压缩文件
* zippath 压缩源文件路径
* zipFileName 压缩目标文件路径,需要是一个文件名,且必须存在(Fileoutstream调用)
*/
public String Tozip(String dirpath, String zipFileName) {
String str = null;
try {
File zipFile = new File(zipFileName);
if (zipFile.exists()) {
zipFile.delete();
}
zipFile.createNewFile();//创建文件
FileOutputStream fos = new FileOutputStream(zipFile);
BufferedOutputStream bos = new BufferedOutputStream(fos, 1024);
ZipOutputStream zos = new ZipOutputStream(bos);//压缩输出流
File dirFile = new File(dirpath);
if (dirFile.isDirectory()) {
str = directoryZip(zos, dirFile, "");
} else {//压缩单文件
str = onefilezip(dirFile, zos, zipFile);
}
zos.close();
bos.close();
fos.close();
}
catch (Exception e){
e.printStackTrace();
}
//返回压缩后文件路径
return str;
}
/**
* 压缩文件夹
* 添加到压缩文件中
* @param out 源文件流对象
* @param f 目地文件对象
* @param base 用于子目录录入
* @throws Exception
*/
private String directoryZip(ZipOutputStream out, File f, String base) throws Exception {
// 如果传入的是目录
if (f.isDirectory()) {
File[] fl = f.listFiles();
// 创建压缩的子目录
out.putNextEntry(new ZipEntry(base + "/"));
if (base.length() == 0) {
base = "";
} else {
base = base + "/";
}
for (int i = 0; i < fl.length; i++) {
directoryZip(out, fl[i], base + fl[i].getName());
}
} else {
File file = new File(base);
onefilezip(f, out, file);
}
System.out.println("file compress:" + f.getCanonicalPath());
//表示与此抽象路径名相同的文件或目录的规范路径名字符串
return f.getCanonicalPath();
}
public String onefilezip(File dirFile, ZipOutputStream zos, File zipFile) {
byte[] buffer = new byte[1024];
ZipEntry zipEntry = null;
int readLength = 0; //每次读取出来的长度
InputStream is = null;
String str = null;
try {
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(dirFile));
DataInputStream dis = new DataInputStream(bin);//增强
//输出-写出数据
zipEntry = new ZipEntry(dirFile.getName()); //获得压缩文件条目
zos.putNextEntry(zipEntry);
while ((readLength = dis.read(buffer)) != -1) {//每次读取1024(缓冲区大小)
zos.write(buffer, 0, readLength);
zos.flush();
}
str = zipFile.getCanonicalPath();
System.out.println("file compress:" + zipFile.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}
刚开始编写压缩代码的时候并没有使用BufferedInputStream,DataInputStream,只是简单的使用 FileInputStream去进行压缩,于是压缩文件打不开,压缩文件损坏。。。。特别是对图片进行压缩,最是让我头疼,最后找到了这个增强方法,使用后,嗯,NIce!VeryGood!
对于压缩途中数据出错问题,还有几个检查的类,例如 CheckedOutputStream(对输出文件做CRC32校验)感兴趣的,有需要的可以自行搜索。
解压流程及代码
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class Unzip {
//把zip解压缩到path下
// 文件对象,解压路径 File file, String path
public boolean unzip(String filepath, String unpath) {
File file = new File(filepath);
try {
ZipFile zip = new ZipFile(file);
for (Enumeration<?> entries = zip.entries(); entries.hasMoreElements(); ) {
ZipEntry entry = (ZipEntry) entries.nextElement();
String name = entry.getName();
System.out.println("解压:" + name);
unprocess(entry,unpath,zip,name);
}
} catch (IOException e) {
}
return true;
}
private void unprocess(ZipEntry entry,String unpath,ZipFile zip,String name){
try {
if (entry.isDirectory()) {
File dir = new File(unpath + File.separator + name);
dir.mkdir();
} else {
File unfile = new File(unpath + File.separator + name);
if (!unfile.getParentFile().exists())
unfile.getParentFile().mkdirs();
unfile.createNewFile();
InputStream in = zip.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(unfile);
int len;
byte[] buf = new byte[1024 * 20];
while ((len = in.read(buf)) != -1) {
fos.write(buf, 0, len);
fos.flush();
}
fos.close();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//循环输出文件名
// private void printzipFile(File dfile) {
// if (dfile.exists()) {
// if (dfile.isFile()) {
// System.out.println(dfile.toString());
// return;
// }
// if (dfile.isDirectory()) {
// System.out.println(dfile.toString());
// File[] files = dfile.listFiles();
// for (int i = 0; i < files.length; i++) {
// printzipFile(files[i]);
// }
// }
// }
// return;
// }
}
对文件路径处理
我在进行压缩和解压的时候,对路径的处理单独列出了一个类,因为要处理多种情况:
首先源文件夹路径是必须有的,无论是压缩还是解压
1.目的路径无,默认其压缩到当前文件夹下
2.目的路径非当前文件夹下,这种就直接传递过去就可以
压缩:
要求更改压缩文件后缀名,这就要对上面两个问题再判断
解压:
解压时同样考虑1,2两种情况,但是解压出来是文件夹,路径名就不同了,就要和压缩分开考虑,于是又定义两个个方法。。。
import java.io.File;
public class Getpath {
//suffix 后缀名
public String getzpath(String filepath, String targetpath, String suffix) {
String path = null;
int f = filepath.lastIndexOf("\\");
int t = targetpath.length();
if (f == t || targetpath == null) {
path = getCzippath(filepath, suffix);
} else {
path = getzippath(filepath, targetpath, suffix);
}
return path;
}
//当前文件夹下
private String getCzippath(String Cfilepath, String suffix) {
String zipfilename = null;
if (suffix == null || suffix.length() <= 0) {
suffix = "zip";
}
int indexof = Cfilepath.lastIndexOf(".");
if (indexof == -1 && indexof <= 0) {
zipfilename = Cfilepath + "." + suffix;
} else {
zipfilename = Cfilepath.substring(0, indexof + 1) + suffix;
}
//返回压缩文件夹路径
return zipfilename;
}
//zipfilepath:要压缩到的文件夹路径 filepath:源文件路径 suffix 后缀名
private String getzippath(String filepath, String zipfilepath, String suffix) {
String zipfilename = null;
if (suffix == null || suffix.length() <= 0) {
suffix = "zip";
}
File file = new File(filepath);
int indexof = file.getName().lastIndexOf(".");
if (indexof == -1 && indexof <= 0) {
zipfilename = zipfilepath + "\\" + file.getName() + "." + suffix;
} else {
//目标文件夹路径+文件名(去后缀,保留.)+zip
zipfilename = zipfilepath + "\\" + file.getName().substring(0, indexof + 1) + suffix;
}
return zipfilename;
}
public String getunpath(String filepath, String targetpath) {
String path = null;
int f = filepath.lastIndexOf("\\");
int t = targetpath.length();
if (f == t || targetpath == null) {
path = getCunzippath(filepath);
} else {
path = getunzippath(filepath, targetpath);
}
return path;
}
private String getCunzippath(String Cfilepath) {
int indexof = Cfilepath.lastIndexOf(".");
if (indexof == -1 && indexof <= 0) {
} else {
Cfilepath = Cfilepath.substring(0, indexof);
}
//返回压缩文件夹路径
return Cfilepath;
}
private String getunzippath(String filepath, String targetpath) {
File file = new File(filepath);
int indexof = file.getName().lastIndexOf(".");
if (indexof == -1 && indexof <= 0) {
targetpath = targetpath + "\\" + file.getName();
} else {
//目标文件夹路径+文件名(去后缀,保留.)+zip
targetpath = targetpath + "\\" + file.getName().substring(0, indexof);
}
return targetpath;
}
}
附赠 文件过滤,和拷贝
我在进行压缩解压缩的时候,想处理同一个文件夹下的多文件,怎么办–>把它们过滤出来,组成数组,循环处理!又不想对原数据进行处理(要是我写的代码有问题,把原数据整没了怎么办),于是我就i想到复制一份!
过滤代码
(考虑到文件后缀的大小写和格式不同的问题,比如png,jpg;于是写了一个能过滤两个后缀名的方法)
import java.io.File;
import java.io.FilenameFilter;
public class Filterfile implements FilenameFilter {
private String suffix;//后缀名
public void setsuffix(String suffix) {
this.suffix = suffix;
}
public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
//多文件名后缀筛选File dirFile, String s1, String s2
public String[] filterfile(File dirFile, String s1, String s2) {
this.setsuffix(s1);
String[] results1 = dirFile.list(this);
this.setsuffix(s2);
String[] results2 = dirFile.list(this);
//合并数组
String[] results = new String[results1.length + results2.length];
System.arraycopy(results1, 0, results, 0, results1.length);
System.arraycopy(results2, 0, results, results1.length, results2.length);
return results;
}
}
//使用例
File dirfile = new File("筛选文件所在的文件夹路径");
Filterfile filter = new Filterfile();
String result = dirFile.list(filter);//单文件后缀名
String[] results = filter .filterfile(dirFile, s1, s2);//s1,s2:两个后缀
方法返回的是文件名数组(不是绝对路径)
关于FilenameFilter接口,推荐一篇文章:FilenameFilter接口详解
拷贝部分
import interfaceclass.Icopy;
import java.io.*;
import java.util.ArrayList;
public class Copy implements Icopy {
public Copy() {
}
/**
* 配合文件筛选方法使用
* @param path 源文件路径
* @param results 筛选文件名数组
* @param realPath 处理后,目标路径
*/
public void TocNewFile(String path, String[] results, String realPath) {
//为文件添加路径
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < results.length; i++) {
list.add(path + "\\" + results[i]);
}
System.out.println("筛选出的文件的路径:");
for (String name : list) {
System.out.println(name);
}
//判断解压目标文件夹是否存在
File realfile = new File(realPath);
if (!realfile.exists()) {//如果文件夹不存在
realfile.mkdir();//创建文件夹
}
//循环解压
for (int i = 0; i < list.size(); i++) {
cNewFile(path, realPath, results[i]);
}
}
private File cNewFile(String path, String realpath, String newFileName) {
File file = new File(path); // path原文件路径,被复制的文件
File dir = new File(realpath); // realPath复制的目标路径
if (!dir.exists()) { // 判断路径是否存在
dir.mkdirs();
}
File newFile = new File(realpath, newFileName); // 创建新文件对象
try {
newFile.createNewFile(); // 创建新文件
fileChannelCopy(file, newFile); // 复制模板到新文件
} catch (Exception e) {
e.printStackTrace();
}
return newFile;
}
// 以文件通道的方式读取、写入文件
private void fileChannelCopy(File s, File t) {
try {
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(new FileInputStream(s), 1024);
out = new BufferedOutputStream(new FileOutputStream(t), 1024);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
} finally {
if (null != in) {
in.close();
}
if (null != out) {
out.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
十分感谢CSDN上的博主们,分享的经验与代码
因为开始敲代码的时候也没想过写一篇文章,觉得压缩和解压缩是比较简单的事情(于是就没记下那些文章地址,一周后,难寻…),等到实际去做才知道360压缩之类的压缩工具背后隐藏的一角。突然就有了—路漫漫其修远兮,吾将上下而求索。 的感悟!
最后再次强调,部分代码确实参考(嗯,文化人,参考!)其他文章,侵删。