1

My Spring Boot application has the standard structure of src: main, test each of which has a /resources subfolder.

enter image description here

I need to reference an existing file under /resources. When I do

InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("file.txt");

everything works great. But when I construct a File as follows, including with classpath:, the file is invalid and file.isValid() returns false.

    File f1 = new File("file.txt");
    File f2 = new File("classpath:file.txt");
    File f3 = new File("resources/file.txt");
    File f4 = new File("classpath:resources/file.txt");
    File f5 = new File("/resources/file.txt");
    File f6 = new File("classpath:/resources/file.txt");
    File f7 = new File("classpath:/file.txt");

I can't use anything involving getClass().getClassLoader().getResource() and must use a dynamic file path because I'm dealing with a property which works (1) either from a classpath reference in the source code or (2) as a real file, overridden on the server. So I have to get File objects in a uniform way -- it's a single property referencing this file. Are there any solutions?

e.g.

file_location = classpath:file.txt # for local testing
file_location = /opt/dir/file.txt # server override

This thread says that ClassLoader/Resource methods must be used with File.

gene b.
  • 10,512
  • 21
  • 115
  • 227
  • how about using the `ResourceLoader`? https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/ResourceLoader.html#getResource(java.lang.String) – dey Mar 26 '23 at 15:13
  • I know. Can't use it because I have a uniform property which must either reference a Resources file, or a regular non-resource file (as described above). – gene b. Mar 26 '23 at 15:14
  • but with ResourceLoader you can use e.g.: "file:C:/test.dat" – dey Mar 26 '23 at 15:17
  • Spring!? - easy-"peasy":`@Value("${file_location}")Resource myRss;` https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources !? – xerx593 Mar 26 '23 at 15:26
  • @dey Yes, I can, but the DevOps team has a Helm chart which lists normal absolute paths for this property, rather than `file:C:/...`. I think I might need a custom If-Else utility method to decide based on the presence of the substring `classpath:`. – gene b. Mar 26 '23 at 15:29

1 Answers1

0

I ended up writing my own utility method that returns a File from either pathway.

public static File getFileFromClasspathOrAbsolutePath(String filePath) {
    
    File file = null;
    
    if (filePath != null) {
        if (filePath.startsWith(Constants.FILENAME_PATH_CLASSNAME_PREFIX)) { // "classpath:"
            URL url = Utils.class.getClassLoader().getResource(filePath.replace(Constants.FILENAME_PATH_CLASSNAME_PREFIX, ""));
            if (url != null) {
                file = new File(url.getFile());
            }
        } else {
            file = new File(filePath);
        }
    }
    
    return file;
}
gene b.
  • 10,512
  • 21
  • 115
  • 227