java生成zip压缩文件
程序员文章站
2022-06-07 15:21:58
...
jdk自身有zip相关的代码,不过直到1.6的版本没有提供设置字符集的接口,因此都会出现中文乱码,目前网上的方案大多需要引入ant包进行处理:
然而,1.7已经修复了这个问题
在jdk7中的java.util.zip.ZipOutputStream新增了这样一个构造方法:
这就为我们设置字符集提供了接口
这样一来两个方法基本来说可以算是等效了,后面的新增文件方法都相同的
给一个使用jdk自带ZipOutputStream的直接取得zip文件字节数组的方案
引入了两个commons包,给出Maven Dependency
测试:
注意这个案例因为要把zip压缩文件整体读入内存所以如果压的文件体积太大就会......
//创建org.apache.tools.zip.ZipOutputStream ZipOutputStream zos = new ZipOutputStream(cos); zos.setEncoding("gbk");
然而,1.7已经修复了这个问题
在jdk7中的java.util.zip.ZipOutputStream新增了这样一个构造方法:
/** * Creates a new ZIP output stream. * * @param out the actual output stream * * @param charset the {@linkplain java.nio.charset.Charset charset} * to be used to encode the entry names and comments * * @since 1.7 */ public ZipOutputStream(OutputStream out, Charset charset) { super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); if (charset == null) throw new NullPointerException("charset is null"); this.zc = ZipCoder.get(charset); usesDefaultDeflater = true; }
这就为我们设置字符集提供了接口
ZipOutputStream zos = new ZipOutputStream(cos, Charset.forName("gbk"));
这样一来两个方法基本来说可以算是等效了,后面的新增文件方法都相同的
给一个使用jdk自带ZipOutputStream的直接取得zip文件字节数组的方案
import org.apache.commons.io.FileUtils; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.RandomStringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.nio.charset.Charset; import java.util.HashSet; import java.util.Set; import java.util.zip.CRC32; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * Created with IntelliJ IDEA. * User: yixian * Date: 13-10-17 * Time: 下午2:52 * 将文件夹压缩并取回zip文件byte[] */ public class DefaultZipper implements IZipper { private Set<String> filePathSet = new HashSet<String>(); private File targetFile; private Logger logger = LoggerFactory.getLogger(getClass()); public DefaultZipper() { String tempDirectory = FileUtils.getTempDirectoryPath(); if (!tempDirectory.endsWith(File.separator)) { tempDirectory += File.separator; } targetFile = initRandomTarget(tempDirectory); } private synchronized File initRandomTarget(String tempDirectory) { File target; do { String fileName = RandomStringUtils.random(20, true, true); String targetFilePath = tempDirectory + fileName; target = new File(targetFilePath); } while (target.exists()); return target; } private boolean checkFilePath(String path) { File file = new File(path); return file.exists(); } @Override public boolean addFile(String filePath) { if (checkFilePath(filePath)) { filePathSet.add(filePath); return true; } return false; } @Override public String[] addFiles(String... paths) { String[] notExistsFiles = new String[0]; for (String path : paths) { if (!addFile(path)) { ArrayUtils.add(notExistsFiles, path); } } return notExistsFiles; } @Override public byte[] doCompress() throws IOException { FileOutputStream fos = new FileOutputStream(targetFile); CheckedOutputStream cos = new CheckedOutputStream(fos, new CRC32()); ZipOutputStream zos = new ZipOutputStream(cos, Charset.forName("gbk")); String baseDir = ""; for (String filePath : filePathSet) { compress(new File(filePath), zos, baseDir); } zos.close(); return loadTargetFileBytes(); } private void compress(File file, ZipOutputStream zos, String basePath) { if (file.isDirectory()) { logger.debug("compressing dir:" + basePath + file.getName()); compressDirectory(file, zos, basePath); } else { logger.debug("compressing file:" + basePath + file.getName()); compressFile(file, zos, basePath); } } private void compressDirectory(File dir, ZipOutputStream zos, String basePath) { File[] childrenFiles = dir.listFiles(); for (File child : childrenFiles != null ? childrenFiles : new File[0]) { compress(child, zos, basePath + dir.getName() + "/"); } } private void compressFile(File file, ZipOutputStream zos, String basePath) { if (!file.exists()) { return; } try { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); String entryName = basePath + file.getName(); ZipEntry entry = new ZipEntry(entryName); zos.putNextEntry(entry); byte[] buffer = FileUtils.readFileToByteArray(file); zos.write(buffer); zos.flush(); zos.closeEntry(); bis.close(); } catch (IOException ignored) { } } private byte[] loadTargetFileBytes() { try { byte[] fileBytes = FileUtils.readFileToByteArray(targetFile); boolean deleted = targetFile.delete(); logger.debug("file:" + targetFile.getAbsoluteFile() + " deleted:" + deleted); return fileBytes; } catch (IOException e) { return new byte[0]; } } }
引入了两个commons包,给出Maven Dependency
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency>
测试:
import com.skytech.crius.city.util.DefaultZipper; import org.junit.Test; import java.io.FileOutputStream; import java.io.IOException; /** * Created with IntelliJ IDEA. * User: yixian * Date: 13-10-21 * Time: 上午10:30 */ public class ZipTest { private static final String SOURCE_FILE_PATH = "d:\\foo\\bar"; @Test public void DefaultZipperTest() throws IOException { IZipper zipper = new DefaultZipper(); zipper.addFile(SOURCE_FILE_PATH); byte[] bytes = zipper.doCompress(); FileOutputStream fos = new FileOutputStream("d:\\test.zip"); fos.write(bytes); fos.flush(); fos.close(); } }
注意这个案例因为要把zip压缩文件整体读入内存所以如果压的文件体积太大就会......