Reading files in a SpringBoot 2.0.1.RELEASE app

北战南征 提交于 2019-12-05 22:44:47

I found the combination of ResourceLoader and ResourcePatternUtils to be the most optimum way of listing/reading files from a classpath resource folder in a Spring Boot application:

@RestController
public class ExampleController {

    private ResourceLoader resourceLoader;

    @Autowired
    public ExampleController(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    private List<String> getFiles() throws IOException {
        Resource[] resources = ResourcePatternUtils
                .getResourcePatternResolver(loader)
                .getResources("classpath*:elcordelaciutat/*.txt");

        return Arrays.stream(resources)
                   .map(p -> p.getFilename().toUpperCase())
                   .sorted()
                   .collect(toList());

    }
}

Updates

If you want to fetch all the files including the files in subfolders of elcordelaciutat, you need to include the following pattern classpath*:elcordelaciutat/**. This would retrieve the files in the subfolders including the subfolders. Once you get all the resources, filter them based on .txt file extension. Here are the changes you need to make:

private List<String> getFiles() throws IOException {
    Resource[] resources = ResourcePatternUtils
            .getResourcePatternResolver(loader)
            // notice **
            .getResources("classpath*:elcordelaciutat/**");

    return Arrays.stream(resources)
               .filter(p -> p.getFilename().endsWith(".txt"))
               .map(p -> {
                   try {
                       String path = p.getURI().toString();
                       String partialPath = path.substring(
                           path.indexOf("elcordelaciutat"));
                       return partialPath;
                   } catch (IOException e) {
                            e.printStackTrace();
                   }

                   return "";
                })
               .sorted()
               .collect(toList());
}

Let's say if you have the following resources folder structure:

+ resources
  + elcordelaciutat
    - FileA.txt
    - FileB.txt
    + a-dir
      - c.txt
      + c-dir
        - d.txt
    + b-dir
      - b.txt

After filtering, the list will contain the following strings:

  • elcordelaciutat/FileA.txt
  • elcordelaciutat/FileB.txt
  • elcordelaciutat/a-dir/c-dir/d.txt
  • elcordelaciutat/a-dir/c.txt
  • elcordelaciutat/b-dir/b.txt

Note

When you want to read a resource, you should always use the method getInputStream().

When you start your project from Eclipse, the generated class files and resources are actually just files and folders on your hard drive. This is why it works to iterate over these files with the File class.

When you build a jar, all content is actually ziped and stored in a single archive. You can not access is with file system level tools any more, thus your FileNotFound exception.

Try something like this with the JarURL:

JarURLConnection connection = (JarURLConnection) url.openConnection();
JarFile file = connection.getJarFile();
Enumeration<JarEntry> entries = file.entries();
while (entries.hasMoreElements()) {
    JarEntry e = entries.nextElement();
    if (e.getName(). endsWith("txt")) {
        // ...
   }
}
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StreamUtils;
...
private static final String CURRENT_FILE = "file.txt";

public Resource getCurrentResource() {
    return new ClassPathResource(CURRENT_FILE);
}

Later in client code or in code of some other module code you can even get its bytes:

...
Resource resource = getCurrentResource();
byte[] data = StreamUtils.copyToByteArray(resource.getInputStream());
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!