0

How to read files from the sub folder of resource folder with using URI

    How to read files from the sub folder of resource folder.

I have some json file in resources folder like :

src 
    main
        resources 
            jsonData
                d1.json
                d2.json
                d3.json

Now I want to read this in my class which is

src 
    main
        java
            com
                myFile
                    classes 

here is what I am trying.

 File[] fileList = (new File(getClass().getResource("/jaonData").toURI())).listFiles();
    
            for (File file : listOfFiles) {
                if (file.isFile()) {
                   // my operation of Data.
                }
            }

my things are working fine but the problem what I am getting is i don't want to use toURI as it is getting failed.

David
  • 4,266
  • 8
  • 34
  • 69

1 Answers1

0

You're probably not using Spring Boot, so how to read folder from the resolurces files in spring boot, : Getting error while running from Jar won't help you much.

I'll repeat myself from a comment to that question:

Everything inside a JAR file is not a file, and cannot be accessed using File, FileInputStream, etc. There are no official mechanisms to access directories in JAR files.

Fortunately, there is a non-official way, and that uses the fact that you can open a JAR file as a separate file system.

Here's a way that works both with file-based file systems and resources in a JAR file:

private void process() throws IOException {
    Path classBase = getClassBase();
    if (Files.isDirectory(classBase)) {
        process(classBase);
    } else {
        // classBase is the JAR file; open it as a file system
        try (FileSystem fs = FileSystems.newFileSystem(classBase, getClass().getClassLoader())) {
            Path root = fs.getPath("/");
            return loadFromBasePath(root);
        }
    }
} 

private Path getClassBase() {
    ProtectionDomain protectionDomain = getClass().getProtectionDomain();
    CodeSource codeSource = protectionDomain.getCodeSource();
    URL location = codeSource.getLocation();
    try {
        return Paths.get(location.toURI());
    } catch (URISyntaxException e) {
        throw new IllegalStateException(e);
    }
}

private void processRoot(Path root) throws IOException {
    // use root as if it's either the root of the JAR, or target/classes
    // for instance
    Path jsonData = root.resolve("jsonData");
    // Use Files.walk or Files.newDirectoryStream(jsonData)
}

If you don't like using ProtectionDomain, you can use another little trick, that makes use of the fact that every class file can be read as resource:

private Path getClassBase() {
    String resourcePath = '/' + getClass().getName().replace('.', '/') + ".class";
    URL url = getClass().getResource(resourcePath);
    String uriValue = url.toString();
    if (uriValue.endsWith('!' + resourcePath)) {
        // format: jar:<file>!<resourcePath>
        uriValue = uriValue.substring(4, uriValue.length() - resourcePath.length() - 1);
    } else {
        // format: <folder><resourcePath>
        uriValue = uriValue.substring(0, uriValue.length() - resourcePath.length());
    }
    return Paths.get(URI.create(uriValue));
}
Rob Spoor
  • 6,186
  • 1
  • 19
  • 20
  • Thanks for answer. I am using the this way where exactly I am reading the file `Object obj = parser.parse(new FileReader(filename.toString)));` – David Oct 01 '22 at 15:44
  • When you're working with `Path` instead of `File`, use `Files.newBufferedReader(path)` instead of `FileReader`. – Rob Spoor Oct 01 '22 at 15:51
  • I appreciate your effort, @value i am using and that works for all 4 files. Thanks !!\ Little new in Java so understanding terminology. – David Oct 01 '22 at 15:58
  • This is not reliable. [ProtectionDomain.getCodeSource() can return null](https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/security/ProtectionDomain.html#getCodeSource()) and there are many environments where .jar files are not paths in a file system. – VGR Oct 02 '22 at 16:36
  • @VGR that's why I added the alternative. – Rob Spoor Oct 03 '22 at 17:41
  • And that’s why I pointed out that there are many environments where .jar files are not paths in a file system, which means Paths.get will fail. – VGR Oct 03 '22 at 20:29
  • @VGR you missed that I used `Paths.get` with a URI, not a string. That means that, as long as there's a `FileSystemProvider` registered for the URI's scheme, the call will **not** fail. – Rob Spoor Oct 04 '22 at 07:47
  • True, but there is only one provider by default, so that code will fail for non-file .jars, unless explicit steps are taken to install more providers. – VGR Oct 04 '22 at 12:12