-1

How do I copy a file from D:\test\ folder to D:\test.zip using java.nio.files.Files? I got NoSuchFileException: D:\Ausbildungsnachweise\Ausbildungsnachweis_Technisch_Form.doc -> D:\test.zip\Ausbildungsnachweis_Technisch_Form.doc as exception. I think i am using the right pathes, but no idea why this error occurs, since the paths do exist.

My whole method:

Map<String, String> env = Collections.singletonMap("create", "true");
Path dir = Paths.get(destinationFolder.getAbsolutePath());
Path destination = dir.resolve(zipNameGenerator.getName() + fileEnding);
URI uri = URI.create("jar:" + destination.toUri());

try {
    FileSystem fs;
    if (overwriteZipWithSameName || !Files.exists(destination)) {
        fs = FileSystems.newFileSystem(uri, env);
    } else {
        fs = FileSystems.getFileSystem(uri);
    }
    for (String file : sourceFolder.list(filenameFilter)) {
        Files.copy(sourceFolder.toPath().resolve(file), fs.getPath(file));
    }
} catch (IOException e1) {
    e1.printStackTrace();
}
XtremeBaumer
  • 6,275
  • 3
  • 19
  • 65

1 Answers1

2
URI uri = new URI("jar:file:/D:/test.zip");

No, it should be jar:file:///D:/test.zip. But the most portable way of doing it is:

Path dir = Paths.get("D:\\");
Path file = dir.resolve("test.zip");
URI uri = URI.create("jar:" + file.toUri());

Similarly, where you do:

Paths.get(sourceFolder + "\\" + file)

it's more portable to do:

sourceFolder.resolve(file)

(for example, if you run the application on Linux in the future, the "\" won't work.)

Also, you could make your map more succinctly like this:

Map<String, String> env = Collections.singletonMap("create", "true");

UPDATE:

Following your updated code and your comment below, I've created a working main class, shown below, reusing as much of your existing code as possible while correcting where necessary. Note that you need to use newFileSystem() even for existing zip files. The getFileSystem() call assumes you've already created a FileSystem object somewhere else in your code, which is cached by the file system provider, and FileSystems.getFileSystem() returns a reference to the already existing object. Also, FileSystem is Closeable, so use it in a try-with-resources statement.

Complete class, fully working:

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URI;
import java.nio.file.*;
import java.util.Collections;
import java.util.Map;

public class SOQn47577298 {
    private final static Map<String, String> CREATE_TRUE =
            Collections.singletonMap("create", "true");

    interface ZipNameGenerator {
        String getName();
    }

    static void copyFileToZip(
            File sourceFolder,
            FilenameFilter filenameFilter,
            File destinationFolder,
            ZipNameGenerator zipNameGenerator,
            String fileEnding,
            boolean overwriteZipWithSameName) throws IOException {

        Path dir = Paths.get(destinationFolder.getAbsolutePath());
        Path destination = dir.resolve(zipNameGenerator.getName() + fileEnding);
        URI uri = URI.create("jar:" + destination.toUri());

        final Map<String, String> env;
        if (overwriteZipWithSameName || !Files.exists(destination)) {
            env = CREATE_TRUE;
        } else {
            env = Collections.emptyMap();
        }

        try (FileSystem fs = FileSystems.newFileSystem(uri, env)){
            for (String file : sourceFolder.list(filenameFilter)) {
                Path source = sourceFolder.toPath().resolve(file);
                Path dest = fs.getPath(file);
                Files.copy(source, dest);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        final File source = new File("D:\\Ausbildungsnachweise");
        final FilenameFilter nameFilter = (dir, name) -> name.endsWith(".doc");
        final File dest = new File("D:\\");
        final ZipNameGenerator zipNameGnr = () -> "test";
        final String fileEnding = ".zip";
        final boolean overwrite = false;

        copyFileToZip(source, nameFilter, dest, zipNameGnr, fileEnding, overwrite);
    }
}
DodgyCodeException
  • 5,963
  • 3
  • 21
  • 42
  • Thanks for your tips, really appreciate it. Sadly I can't create a file from the `URI uri`. It throws `IllegalArgumentException: URI is not hierarchical`. I need the file of my destination to check if the file already exists or if i need a new one – XtremeBaumer Dec 01 '17 at 07:17
  • @XtremeBaumer that shouldn't be a problem. Where do you get this error? Is it when you call `Files.exists(uri)`? You shouldn't be passing a uri to Files.exists; just pass a Path (without the jar: in front). – DodgyCodeException Dec 01 '17 at 08:00
  • Okay, now it properly creates a new zip file if none exists, but I also need to open existing zip files. If I try that, it throws `FileSystemNotFoundException` on `fs = FileSystems.getFileSystem(uri);`. Also my copying doesn't do anything. (updated code) – XtremeBaumer Dec 01 '17 at 08:13
  • Could you maybe give a working example of copying files? with `Files.copy(sourceFolder.toPath().resolve(file), new File(destination.resolve(file).toString()).toPath());` i get this exception `NoSuchFileException: D:\Ausbildungsnachweise\Ausbildungsnachweis_Technisch_Form.doc -> D:\test.zip\Ausbildungsnachweis_Technisch_Form.doc`. Source file exists and desination directory exists too. – XtremeBaumer Dec 01 '17 at 08:34
  • Did my updated code (including the self-contained demo application class) work for you? – DodgyCodeException Dec 04 '17 at 10:03
  • I used another way now (`ZipOutputStream`) to accomplish this task. Still thanks for the update and the code as well. It might help others (or me) to use `FileSystem` properly – XtremeBaumer Dec 04 '17 at 12:59