Eri*_*ric 41 java directory zip structure
在尝试使用java.util.zip
我压缩存档时,遇到了很多问题,我解决了大部分问题.现在我终于得到了一些输出,我很难获得"正确"的输出.我有一个提取的ODT文件(目录将更符合描述)我做了一些修改.现在我想压缩该目录以重新创建ODT文件结构.压缩目录并将其重命名为.odt结束工作正常,所以应该没有问题.
主要问题是我丢失了目录的内部结构.一切都变得"平坦",我似乎找不到保留原始多层结构的方法.我希望得到一些帮助,因为我似乎无法找到问题.
以下是相关的代码段:
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
FILEPATH.substring(0, FILEPATH.lastIndexOf(SEPARATOR) + 1).concat("test.zip")));
compressDirectory(TEMPARCH, out);
Run Code Online (Sandbox Code Playgroud)
这SEPARATOR
是系统文件分隔符,FILEPATH
是原始ODT的文件路径,我将覆盖但尚未在此处进行测试.我只是写入同一目录中的test.zip文件.
private void compressDirectory(String directory, ZipOutputStream out) throws IOException
{
File fileToCompress = new File(directory);
// list contents.
String[] contents = fileToCompress.list();
// iterate through directory and compress files.
for(int i = 0; i < contents.length; i++)
{
File f = new File(directory, contents[i]);
// testing type. directories and files have to be treated separately.
if(f.isDirectory())
{
// add empty directory
out.putNextEntry(new ZipEntry(f.getName() + SEPARATOR));
// initiate recursive call
compressDirectory(f.getPath(), out);
// continue the iteration
continue;
}else{
// prepare stream to read file.
FileInputStream in = new FileInputStream(f);
// create ZipEntry and add to outputting stream.
out.putNextEntry(new ZipEntry(f.getName()));
// write the data.
int len;
while((len = in.read(data)) > 0)
{
out.write(data, 0, len);
}
out.flush();
out.closeEntry();
in.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
包含要压缩文件的目录位于用户空间中的某个位置,而不是与生成的文件位于同一目录中.我认为这可能是麻烦但我不知道如何.此外,我认为问题可能是使用相同的流输出,但我再也看不出如何.我在一些示例和教程中看到他们使用getPath()
而不是getName()
改变,这给了我一个空的zip文件.
McD*_*ell 94
的URI类是具有相对路径的工作是有用的.
File mydir = new File("C:\\mydir");
File myfile = new File("C:\\mydir\\path\\myfile.txt");
System.out.println(mydir.toURI().relativize(myfile.toURI()).getPath());
Run Code Online (Sandbox Code Playgroud)
上面的代码将发出字符串path/myfile.txt
.
为了完整起见,这是一个zip
归档目录的方法:
public static void zip(File directory, File zipfile) throws IOException {
URI base = directory.toURI();
Deque<File> queue = new LinkedList<File>();
queue.push(directory);
OutputStream out = new FileOutputStream(zipfile);
Closeable res = out;
try {
ZipOutputStream zout = new ZipOutputStream(out);
res = zout;
while (!queue.isEmpty()) {
directory = queue.pop();
for (File kid : directory.listFiles()) {
String name = base.relativize(kid.toURI()).getPath();
if (kid.isDirectory()) {
queue.push(kid);
name = name.endsWith("/") ? name : name + "/";
zout.putNextEntry(new ZipEntry(name));
} else {
zout.putNextEntry(new ZipEntry(name));
copy(kid, zout);
zout.closeEntry();
}
}
}
} finally {
res.close();
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码不会保留日期,我不确定它会如何对符号链接这样的东西做出反应.不尝试添加目录条目,因此不会包含空目录.
相应的unzip
命令:
public static void unzip(File zipfile, File directory) throws IOException {
ZipFile zfile = new ZipFile(zipfile);
Enumeration<? extends ZipEntry> entries = zfile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File file = new File(directory, entry.getName());
if (entry.isDirectory()) {
file.mkdirs();
} else {
file.getParentFile().mkdirs();
InputStream in = zfile.getInputStream(entry);
try {
copy(in, file);
} finally {
in.close();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
他们依赖的实用方法:
private static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
while (true) {
int readCount = in.read(buffer);
if (readCount < 0) {
break;
}
out.write(buffer, 0, readCount);
}
}
private static void copy(File file, OutputStream out) throws IOException {
InputStream in = new FileInputStream(file);
try {
copy(in, out);
} finally {
in.close();
}
}
private static void copy(InputStream in, File file) throws IOException {
OutputStream out = new FileOutputStream(file);
try {
copy(in, out);
} finally {
out.close();
}
}
Run Code Online (Sandbox Code Playgroud)
缓冲区大小完全是任意的.
我在你的代码中看到了2个问题,
我提供自己的版本供您参考.我们使用这个来压缩照片下载所以它适用于各种解压缩程序.它保留了目录结构和时间戳.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
56617 次 |
最近记录: |