15

I am getting this error on the following code (note that this does not happen on my local machine, only on my build server):

Files.readAllBytes(Paths.get(getClass().getResource("/elasticsearch/segmentsIndex.json").toURI()), Charset.defaultCharset());

And the exception:

Caused by: java.nio.file.FileSystemNotFoundException: null
at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171)
at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157)
at java.nio.file.Paths.get(Paths.java:143)

I tried to fix it by following this solution; my code now looks like this:

URI segmentsIndexURI = getClass().getResource("/elasticsearch/segmentsIndex.json").toURI();
Map<String, String> env = new HashMap<>(); 
env.put("create", "true");
FileSystem zipfs = FileSystems.newFileSystem(segmentsIndexURI, env); //exception here
Path segmentsIndexPath = Paths.get(segmentsIndexURI);

I am getting the following exception:

java.lang.IllegalArgumentException: Path component should be '/'
at sun.nio.fs.UnixFileSystemProvider.checkUri(UnixFileSystemProvider.java:77)
at sun.nio.fs.UnixFileSystemProvider.newFileSystem(UnixFileSystemProvider.java:86)
at java.nio.file.FileSystems.newFileSystem(FileSystems.java:326)
at java.nio.file.FileSystems.newFileSystem(FileSystems.java:276)

Nothing seems to work. How am I supposed to build the path to the file?

6
  • 1
    did you note that the exception in question title is not the same as the exception in the post ? please clarify. Commented Apr 20, 2015 at 11:35
  • You're passing the URI of a file as a new file system? I do not know how this can make sense. Commented Apr 20, 2015 at 11:36
  • note that the exception mentioned in the description is the one i am getting after following the solution. the first code snippet is the one throwing the exception in the title... i can include the original exception as well if you like Commented Apr 20, 2015 at 11:36
  • did you open your jar or directory deployment to see if your file is present or not in it? and at the correct place? Commented Apr 20, 2015 at 11:43
  • works fine on my local machine, so i assume it is something to do with the environment, or else the path would not work on local run as wlel Commented Apr 20, 2015 at 11:44

5 Answers 5

30

Don't try to access a resource like a file. Just grab the InputStream and read the data from there:

byte[] data;
try (InputStream in = getClass().getResourceAsStream("/elasticsearch/segmentsIndex.json")) {
    data = in.readAllBytes​(); // usable in Java 9+
    // data = IOUtils.toByteArray(in); // uses Apache commons IO library
}

This example uses the IOUtils class from Apache commons-io library.

If you are targeting Java 9+ you can alternatively use data = in.readAllBytes​();.

Sign up to request clarification or add additional context in comments.

1 Comment

I had to add getClass().getClassLoader()
6

Generally, it is not correct to assume that every resource is a file. Instead, you should obtain the URL/InputStream for that resource and read the bytes from there. Guava can help:

URL url = getClass().getResource("/elasticsearch/segmentsIndex.json");
String content = Resources.toString(url, charset);


Another possible solution, with the InputStream and apache commons: Convert InputStream to byte array in Java .

From a byte[], simply use the String constructor to obtain the content as a string.

Comments

3

If you use Spring, inject resources. Be it a file, or folder, or even multiple files, there are chances, you can do it via injection. Warning: DO NOT use File and Files.walk with the injected resources, otherwise you'll get FileSystemNotFoundException when running as JAR.

This example demonstrates the injection of multiple images located in static/img folder.

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;

@Service
public class StackoverflowService {

    @Value("classpath:static/img/*")
    private Resource[] resources;
    private List<String> filenames;

    @PostConstruct
    void init() {
        final Predicate<String> isJPG = path -> path.endsWith(".jpg");
        final Predicate<String> isPNG = path -> path.endsWith(".png");

        // iterate resources, filter by type and get filenames
        filenames = Arrays.stream(resources)
                .map(Resource::getFilename)
                .filter(isJPG.or(isPNG))
                .collect(Collectors.toList());
    }
}

1 Comment

This is exactly what I needed, didn't know about that injection of Resources[], thanks!
3

You should get the resource through an InputStream and not a File, but there is no need for external libraries.

All you need is a couple of lines of code:

InputStream is = getClass().getResourceAsStream("/elasticsearch/segmentsIndex.json");
java.util.Scanner scanner = new java.util.Scanner(is).useDelimiter("\\A");
String json = scanner.hasNext() ? scanner.next() : "";

You can learn more about that method at https://stackoverflow.com/a/5445161/968244

Comments

0

You should be using getResourceAsStream(…) instead of getResource(…). There are a number of methods to read all bytes into a byte array, e.g. Apache Commons has a utility method to do just that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.