Reading files in a SpringBoot 2.0.1.RELEASE app

陌路散爱 提交于 2019-12-07 17:58:31

问题


I have a SpringBoot 2.0.1.RELEASE mvc application. In the resources folder I have a folder named /elcordelaciutat.

In the controller I have this method to read all the files inside the folder

ClassLoader classLoader = this.getClass().getClassLoader();
        Path configFilePath = Paths.get(classLoader.getResource("elcordelaciutat").toURI());    

        List<String> cintaFileNames = Files.walk(configFilePath)
         .filter(s -> s.toString().endsWith(".txt"))
         .map(p -> p.subpath(8, 9).toString().toUpperCase() + " / " + p.getFileName().toString())
         .sorted()
         .collect(toList());

        return cintaFileNames;

running the app. from Eclipse is working fine, but when I run the app in a Windows Server I got this error:

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(Unknown Source)
    at 

I unzipped the generated jar file and the folder is there !

and the structure of the folders is

elcordelaciutat/folder1/*.txt
elcordelaciutat/folder2/*.txt
elcordelaciutat/folder3/*.txt

回答1:


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().




回答2:


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")) {
        // ...
   }
}



回答3:


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());


来源:https://stackoverflow.com/questions/49774517/reading-files-in-a-springboot-2-0-1-release-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!