include my own version for your reference.
We use this one to zip up photos to download so it works with various unzip programs. It preserves the directory structure and timestamps.

public static void createZipFile(File srcDir, OutputStream out,
boolean verbose) throws IOException { List<String> fileList = listDirectory(srcDir);
ZipOutputStream zout = new ZipOutputStream(out); zout.setLevel(9);
zout.setComment("Zipper v1.2"); for (String fileName : fileList) {
File file = new File(srcDir.getParent(), fileName);
if (verbose)
System.out.println(" adding: " + fileName); // Zip always use / as separator
String zipName = fileName;
if (File.separatorChar != '/')
zipName = fileName.replace(File.separatorChar, '/');
ZipEntry ze;
if (file.isFile()) {
ze = new ZipEntry(zipName);
ze.setTime(file.lastModified());
zout.putNextEntry(ze);
FileInputStream fin = new FileInputStream(file);
byte[] buffer = new byte[4096];
for (int n; (n = fin.read(buffer)) > 0;)
zout.write(buffer, 0, n);
fin.close();
} else {
ze = new ZipEntry(zipName + '/');
ze.setTime(file.lastModified());
zout.putNextEntry(ze);
}
}
zout.close();
} public static List<String> listDirectory(File directory)
throws IOException { Stack<String> stack = new Stack<String>();
List<String> list = new ArrayList<String>(); // If it's a file, just return itself
if (directory.isFile()) {
if (directory.canRead())
list.add(directory.getName());
return list;
} // Traverse the directory in width-first manner, no-recursively
String root = directory.getParent();
stack.push(directory.getName());
while (!stack.empty()) {
String current = (String) stack.pop();
File curDir = new File(root, current);
String[] fileList = curDir.list();
if (fileList != null) {
for (String entry : fileList) {
File f = new File(curDir, entry);
if (f.isFile()) {
if (f.canRead()) {
list.add(current + File.separator + entry);
} else {
System.err.println("File " + f.getPath()
+ " is unreadable");
throw new IOException("Can't read file: "
+ f.getPath());
}
} else if (f.isDirectory()) {
list.add(current + File.separator + entry);
stack.push(current + File.separator + f.getName());
} else {
throw new IOException("Unknown entry: " + f.getPath());
}
}
}
}
return list;
}
}

SEPARATOR constant is initialised with the System.getProperty("file.separator") which will give me the OS default file separator.
I would never hardcode a separator since that assumes that your code will only be deployed on a given OS

Don't use File.separator in ZIP. The separator must be "/" according to the spec. If you are on Windows, you must open file as "D:\dir\subdir\file" but ZIP entry must be "dir/subdir/file"

Just go through the source of java.util.zip.ZipEntry. It treats a ZipEntry as directory if its name ends with "/" characters. Just suffix the directory name with "/". Also you need to remove the drive prefix to make it relative.

Here is another example (recursive) which also lets you include/exclude the containing folder form the zip:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; public class ZipUtil { private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; public static void main(String[] args) throws Exception {
zipFile("C:/tmp/demo", "C:/tmp/demo.zip", true);
} public static void zipFile(String fileToZip, String zipFile, boolean excludeContainingFolder)
throws IOException {
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile)); File srcFile = new File(fileToZip);
if(excludeContainingFolder && srcFile.isDirectory()) {
for(String fileName : srcFile.list()) {
addToZip("", fileToZip + "/" + fileName, zipOut);
}
} else {
addToZip("", fileToZip, zipOut);
} zipOut.flush();
zipOut.close(); System.out.println("Successfully created " + zipFile);
} private static void addToZip(String path, String srcFile, ZipOutputStream zipOut)
throws IOException {
File file = new File(srcFile);
String filePath = "".equals(path) ? file.getName() : path + "/" + file.getName();
if (file.isDirectory()) {
for (String fileName : file.list()) {
addToZip(filePath, srcFile + "/" + fileName, zipOut);
}
} else {
zipOut.putNextEntry(new ZipEntry(filePath));
FileInputStream in = new FileInputStream(srcFile); byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int len;
while ((len = in.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
} in.close();
}
}
}

http://stackoverflow.com/questions/1399126/java-util-zip-recreating-directory-structure

java.util.zip - Recreating directory structure(转)的更多相关文章

  1. Java.util.zip adding a new file overwrites entire jar?(转)

    ZIP and TAR fomats (and the old AR format) allow file append without a full rewrite. However: The Ja ...

  2. java.util.zip.ZipException: invalid entry size 解决办法

    启动maven项目时报java.util.zip.ZipException: invalid entry size (expected 7612 but got 5955 bytes) 可能是mave ...

  3. [Java 基础] 使用java.util.zip包压缩和解压缩文件

    reference :  http://www.open-open.com/lib/view/open1381641653833.html Java API中的import java.util.zip ...

  4. 启动TOMCAT报错 java.util.zip.ZipException: invalid LOC header (bad signature)

    报错信息大致如下所示: at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect. ...

  5. java.util.zip.ZipOutputStream压缩无乱码(原创)

    package io; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.FileI ...

  6. [java bug记录] java.util.zip.ZipException: invalid code lengths set

    1. 描述:将代码迁移到maven工程,其中用ZipInputStream读取/src/main/resources下的zip文件时报错:“java.util.zip.ZipException: in ...

  7. java.util.zip压缩打包文件总结二: ZIP解压技术

    一.简述 解压技术和压缩技术正好相反,解压技术要用到的类:由ZipInputStream通过read方法对数据解压,同时需要通过CheckedInputStream设置冗余校验码,如: Checked ...

  8. java.util.zip压缩打包文件总结一:压缩文件及文件下面的文件夹

    一.简述 zip用于压缩和解压文件.使用到的类有:ZipEntry  ZipOutputStream 二.具体实现代码 package com.joyplus.test; import java.io ...

  9. java.util.zip.GZIPInputStream.readUByte,Not in GZIP format错误处理

    问题一: 使用webclient抓取网页时报错:(GZIPInputStream.java:207) atjava.util.zip.GZIPInputStream.readUShort(GZIPIn ...

随机推荐

  1. 自己用js写的两个日历控件

    前一阵写了两个日历控件,做了简单的封装,发出来共朋友们参考. 第一个日历控件,条状的日历. (使用方法:调用initBarTime(id,evn),第一个参数是要渲染div的id,第二个参数是点击日期 ...

  2. Android开发--CardView使用

    Android5.0中向我们介绍了一个全新的控件–CardView,从本质上看,可以将CardView看做是FrameLayout在自身之上添加了圆角和阴影效果.请注意:CardView被包装为一种布 ...

  3. C++界面库

    刚开始用C++做界面的时候,根本不知道怎么用简陋的MFC控件做出比较美观的界面,后来就开始逐渐接触到BCG  Xtreme ToolkitPro v15.0.1,Skin++,等界面库,以及一些网友自 ...

  4. Machine Learning #Lab1# Linear Regression

    Machine Learning Lab1 打算把Andrew Ng教授的#Machine Learning#相关的6个实验一一实现了贴出来- 预计时间长度战线会拉的比較长(毕竟JOS的7级浮屠还没搞 ...

  5. MSSQL - 视图操作

    查询语句(包含使用Where子句): string sql = @"SELECT TableName, TablePosition,TableSate, TabelType,OpenTime ...

  6. Eclipse用法和技巧二十六:浅谈快捷键

    网络上到处都是eclipse有哪些常用的快捷键,其中还有很多讲得着实不错,这里就不再狗尾续貂而是谈谈别的这段时间的一些思考.最近加入了开发团队,代码量突突的上去了,同时也发现关于快捷键还是有很多细节, ...

  7. 用反射,将DataRow行转为Object对象

    /// <summary> /// 反射辅助类 /// </summary> public class ReflectionHelper { /// <summary&g ...

  8. 分布式消息系统jafka快速起步(转)

    Jafka 是一个开源的/性能良好的分布式消息系统.在上一篇文章中有所简单介绍.下面是一篇简单的入门文档.更多详细的文档参考wiki. Step 1: 下载最新的安装包 完整的安装指南在这里.最新的发 ...

  9. VC 对话框背景颜色、控件颜色

    系统环境:Windows 7软件环境:Visual C++ 2008 SP1本次目的:为对话框设置背景颜色.控件颜色 既然MFC对话框不好开发,那么现在我们来开始美化我们的对话框.为对话框设置背景颜色 ...

  10. java web解决表单重复提交问题

    我们大家再进行web开发的时候,必不可少会遇见表单重复提交问题.今天就来给总结如何解决表单提交问题,欢迎大家交流指正. 首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提 ...