Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:递归地将文件添加到zip文件,但不包含完整路径_Java - Fatal编程技术网

Java:递归地将文件添加到zip文件,但不包含完整路径

Java:递归地将文件添加到zip文件,但不包含完整路径,java,Java,我试图将文件夹中的文件按以下结构放入zip文件中: Folder structure: myFolder |-file1.txt |-file2.txt |-folder172 |-file817.txt |-file818.txt ... Supposed structure inside ZipFile: file1.txt file2.txt folder172 |-file817.txt |-file818.txt 这是我的代码: public sta

我试图将文件夹中的文件按以下结构放入zip文件中:

Folder structure:

myFolder
 |-file1.txt
 |-file2.txt
 |-folder172
    |-file817.txt
    |-file818.txt
 ...

Supposed structure inside ZipFile:

file1.txt
file2.txt
folder172
 |-file817.txt
 |-file818.txt
这是我的代码:

public static void writeZip(String path) throws IOException{

    FileOutputStream fos = new FileOutputStream(path+File.separator+"atest.zip");
    ZipOutputStream zos = new ZipOutputStream(fos);

    try {
        Files.walk(Paths.get(path)).filter(Files::isRegularFile).forEach((string) -> addToZipFile(string.toString(),zos));
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    zos.close();
    fos.close();



}


public static void addToZipFile(String fileName, ZipOutputStream zos) throws IOException {

    System.out.println("Writing '" + fileName + "' to zip file");

    File file = new File(fileName);
    FileInputStream fis = null;

    fis = new FileInputStream(file);

    ZipEntry zipEntry = new ZipEntry(fileName);

    zos.putNextEntry(zipEntry);


    byte[] bytes = new byte[1024];
    int length;

    while ((length = fis.read(bytes)) >= 0) {
        zos.write(bytes, 0, length);
    }
    zos.closeEntry();
    fis.close();

}
现在的问题是,当我调用
writeZip(“/home/arthur/.grutil/”)时,我在zip文件中获得以下结构:

home
 |-arthur
    |-.grutil
       |-file1.txt
       |-file2.txt
       |-folder172
          |-file817.txt
          |-file818.txt
   ...

我需要如何更改代码以获得假定的结构(如上所述),而不是具有完整路径“/home/arthur/.grutil/…”的结构?

而这可以通过使用古老的
ZipOutputStream来完成,我建议不要使用它

与字节流相比,将Zip存档看作文件中的压缩文件系统要直观得多。因此,Java提供了

因此,您所需要做的就是将Zip文件作为
文件系统打开
,然后在整个文件系统中手动复制文件

这里有几个问题:

  • 您只需要复制文件,需要创建目录
  • NIOAPI不支持跨不同文件系统的操作,如
    relatiize
    (原因应该很明显),所以这需要您自己完成
  • 这里有几个简单的方法可以做到这一点:

    /**
     * This creates a Zip file at the location specified by zip
     * containing the full directory tree rooted at contents
     *
     * @param zip      the zip file, this must not exist
     * @param contents the root of the directory tree to copy
     * @throws IOException, specific exceptions thrown for specific errors
     */
    public static void createZip(final Path zip, final Path contents) throws IOException {
        if (Files.exists(zip)) {
            throw new FileAlreadyExistsException(zip.toString());
        }
        if (!Files.exists(contents)) {
            throw new FileNotFoundException("The location to zip must exist");
        }
        final Map<String, String> env = new HashMap<>();
        //creates a new Zip file rather than attempting to read an existing one
        env.put("create", "true");
        // locate file system by using the syntax
        // defined in java.net.JarURLConnection
        final URI uri = URI.create("jar:file:/" + zip.toString().replace("\\", "/"));
        try (final FileSystem zipFileSystem = FileSystems.newFileSystem(uri, env);
             final Stream<Path> files = Files.walk(contents)) {
            final Path root = zipFileSystem.getPath("/");
            files.forEach(file -> {
                try {
                    copyToZip(root, contents, file);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }
    
    /**
     * Copy a specific file/folder to the zip archive
     * If the file is a folder, create the folder. Otherwise copy the file
     *
     * @param root     the root of the zip archive
     * @param contents the root of the directory tree being copied, for relativization
     * @param file     the specific file/folder to copy
     */
    private static void copyToZip(final Path root, final Path contents, final Path file) throws IOException {
        final Path to = root.resolve(contents.relativize(file).toString());
        if (Files.isDirectory(file)) {
            Files.createDirectories(to);
        } else {
            Files.copy(file, to);
        }
    }
    
    /**
    *这将在Zip指定的位置创建一个Zip文件
    *包含根在目录中的完整目录树
    *
    *@param zip压缩文件,该文件必须不存在
    *@param包含要复制的目录树的根目录
    *@throws-IOException,针对特定错误引发特定异常
    */
    公共静态void createZip(最终路径zip,最终路径内容)引发IOException{
    if(Files.exists(zip)){
    抛出新的FileReadyExistsException(zip.toString());
    }
    如果(!Files.exists(contents)){
    抛出新的FileNotFoundException(“zip的位置必须存在”);
    }
    final-Map-env=new-HashMap();
    //创建新的Zip文件,而不是尝试读取现有的Zip文件
    环境出售(“创建”、“真实”);
    //使用语法定位文件系统
    //在java.net.JarURLConnection中定义
    最终URI=URI.create(“jar:file:/”+zip.toString().replace(“\\”,“/”));
    try(final FileSystem zipFileSystem=FileSystems.newFileSystem(uri,env);
    最终流文件=文件.walk(目录)){
    最终路径根=zipFileSystem.getPath(“/”);
    files.forEach(文件->{
    试一试{
    copyToZip(根目录、内容、文件);
    }捕获(IOE异常){
    抛出新的运行时异常(e);
    }
    });
    }
    }
    /**
    *将特定文件/文件夹复制到zip存档
    *如果文件是文件夹,请创建该文件夹。否则,请复制该文件
    *
    *@param root压缩文件的根目录
    *@param contents要复制的目录树的根目录,用于相对化
    *@param file要复制的特定文件/文件夹
    */
    私有静态void copyToZip(最终路径根、最终路径内容、最终路径文件)引发IOException{
    最终路径为=root.resolve(contents.relativize(file.toString());
    if(Files.isDirectory(file)){
    创建目录(到);
    }否则{
    文件。复制(文件,到);
    }
    }
    
    如果不这样做,请使用。结合NIOAPI,这使得整个过程非常简单…@Boristespider你知道一些好的网站可以开始使用它吗?在此之前,我从未使用过ZipFilesystem。该链接涵盖了文件的创建和复制。您已经在使用
    Files.walk
    ,它是NIOAPI的一部分。只需确保创建目录并复制文件。。