java.util.zip - 重新创建目录结构 [英] java.util.zip - Recreating directory structure

查看:99
本文介绍了java.util.zip - 重新创建目录结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试使用 java.util.zip 压缩档案时,我遇到了很多问题,我解决了大部分问题。现在我终于得到了一些输出,我很难得到正确的输出。我有一个提取的ODT文件(目录将更适合一个描述),我做了一些修改。现在我想压缩该目录以重新创建ODT文件结构。压缩目录并将其重命名为.odt结束工作正常,所以应该没有问题。



主要的问题是我丢失了目录的内部结构。一切都变得扁平化,我似乎没有找到一种保留原有多层结构的方法。我希望有一些帮助,因为我似乎找不到问题。



以下是相关的代码片段:



pre> ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
FILEPATH.substring(0,FILEPATH.lastIndexOf(SEPARATOR)+ 1).concat(test.zip) ));
compressDirectory(TEMPARCH,out);

SEPARATOR 是系统文件分隔符, FILEPATH 是原始ODT的文件路径,我将覆盖但尚未在此进行测试。我只是写在同一个目录下的test.zip文件。

  private void compressDirectory(String directory,ZipOutputStream out)throws IOException 
{
文件fileToCompress =新建文件(目录);
//列出内容。
String [] contents = fileToCompress.list();
//遍历目录和压缩文件。 (int i = 0; i< contents.length; i ++)
{
文件f =新文件(目录,内容[i]);

//测试类型。目录和文件必须单独对待。
if(f.isDirectory())
{
//添加空目录
out.putNextEntry(new ZipEntry(f.getName()+ SEPARATOR));
//启动递归调用
compressDirectory(f.getPath(),out);
//继续迭代
continue;
} else {
//准备流读取文件。
FileInputStream in = new FileInputStream(f);
//创建ZipEntry并添加到输出流。
out.putNextEntry(new ZipEntry(f.getName()));
//写入数据。
int len;
while((len = in.read(data))> 0)
{
out.write(data,0,len);
}
out.flush();
out.closeEntry();
in.close();
}
}
}

包含文件的目录zip是用户空间中的某个位置,而不是与生成的文件相同的目录。我认为这可能是麻烦,但我不能真正看到如何。另外我想,问题可能是使用相同的流输出,但我再也看不到如何。我在一些例子和教程中看到,他们使用 getPath()而不是 getName(),但改变它给了我一个空的zip文件。

解决方案

URI 类对于使用相对路径非常有用。

 code>文件mydir = new File(C:\\\mydir); 
文件myfile =新文件(C:\\mydir\\\path \\myfile.txt);
System.out.println(mydir.toURI()。relativize(myfile.toURI())。getPath());

上述代码将发出字符串 path / myfile.txt



为了完整起见,这里是一个用于存档目录的 zip 方法:

  public static void zip(文件目录,文件zipfile)throws IOException {
URI base = directory.toURI();
Deque< File> queue = new LinkedList< File>();
queue.push(directory);
OutputStream out = new FileOutputStream(zipfile);
关闭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();
}
}

此代码不保存日期,不知道它会如符号链接这样的东西如何反应。没有尝试添加目录条目,因此不会包括空目录。



相应的 unzip 命令:

  public static void unzip(File zipfile,File directory)throws IOException {
ZipFile zfile = new ZipFile(zipfile) ;
枚举<?扩展ZipEntry> entries = zfile.entries();
while(entries.hasMoreElements()){
ZipEntry entry = entries.nextElement();
文件文件= 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();
}
}
}
}

实用程序他们依赖的方法:

  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();
}
}

缓冲区大小是完全任意的。

While trying to zip an archive using the java.util.zip I ran into a lot of problems most of which I solved. Now that I finally get some output I struggle with getting the "right" output. I have an extracted ODT file (directory would be more fitting a description) to which I did some modifications. Now I want to compress that directory as to recreate the ODT file structure. Zipping the directory and renaming it to end with .odt works fine so there should be no problem.

The main problem is that I lose the internal structure of the directory. Everything becomes "flat" and I do not seem to find a way to preserve the original multi-layered structure. I would appreciate some help on this as I can not seem to find the problem.

Here are the relevant code snippets:

ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
    FILEPATH.substring(0, FILEPATH.lastIndexOf(SEPARATOR) + 1).concat("test.zip")));
    compressDirectory(TEMPARCH, out);

The SEPARATOR is the system file separator and the FILEPATH is the filepath of the original ODT which I will override but have not done here for testing purposes. I simply write to a test.zip file in the same directory.

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();
         }
     }
 }

The directory that contains the files to zip is somewhere in the user space and not in the same directory as the resulting file. I assume this could be trouble but I can not really see how. Also I figured that the problem could be in using the same stream for outputting but again I can not see how. I saw in some examples and tutorials that they use getPath() instead of getName() but changing that gives me an empty zip file.

解决方案

The URI class is useful for working with relative paths.

File mydir = new File("C:\\mydir");
File myfile = new File("C:\\mydir\\path\\myfile.txt");
System.out.println(mydir.toURI().relativize(myfile.toURI()).getPath());

The above code will emit the string path/myfile.txt.

For completeness, here is a zip method for archiving a directory:

  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();
    }
  }

This code makes doesn't preserve dates and I'm not sure how it would react to stuff like symlinks. No attempt is made to add directory entries, so empty directories would not be included.

The corresponding unzip command:

  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();
        }
      }
    }
  }

Utility methods on which they rely:

  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();
    }
  }

The buffer size is entirely arbitrary.

这篇关于java.util.zip - 重新创建目录结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆