在Spring Boot中从类路径资源文件夹的子目录读取文件

7
我想读取资源文件夹的子目录中的文件。 我在jar执行时遇到了问题。
这是我的目录结构。
src/main/resources |_ Conf |_ conf1 |_ config.txt |_ conf2 |_ config.txt
在这里,我正在尝试从“Conf”文件夹的所有子目录中读取“config.txt”文件。我不知道“Conf”将有什么子目录。我知道类路径到“Conf”。因此,我将给出到“Conf”的类路径,并尝试获取子目录和文件。
我尝试使用“ClassPathResource”实现此目标。如果是文件,则可以正常工作。当涉及到目录时,我会遇到问题。我正在使用“getFile”api获取目录路径以遍历该目录的子目录,这会导致在jar执行中出现问题。
以下是我的代码:
以下代码用于读取“Conf”文件夹中的子目录。
List<Map<String,String>> list = new ArrayList<Map<String,String>>();
 ClassPathResource classPathResource = new ClassPathResource("Conf");
 File dir = classPathResource.getFile();
 Files.walk(Paths.get(dir.toString()))
     .filter(Files::isDirectory)
      // This is to exempt current dir.
     .filter((Path p)->!p.toString().equals(dir.toString()))
     .forEach(f-> {list.add(readDirectory(f.toString()));});

读取每个子目录。

public Map<String, String> readDirectory(String dir) {
     Map<String, String> map = new HashMap<String, String>();
     String confDir = dir.substring(dir.lastIndexOf(File.separator)+1);
    try {
          Files.list(Paths.get(dir))
                   .filter(f->f.toString().matches(".*conf\\.txt"))
           .forEach(file ->approvedTermsMap.put
                               (confDir,readFile(file.toFile())));
    } catch (IOException e) {
        e.printStackTrace();
        }
        return map;
 }

读取文件:

public String readFile(File confFile) {

       StringBuffer terms = new StringBuffer();
       try (BufferedReader reader = new BufferedReader(new 
             FileReader(confFile)))
    {
        reader.lines().forEach(term->                    
                             terms.append(term + "|"));
    } catch (FileNotFoundException e) {
            e.printStackTrace();
    } catch (IOException e) {
            e.printStackTrace();
    }
return terms.toString();
}

在这里,我不应该使用classPathResource.getFile()来获取绝对路径,因为它试图在文件系统中查找文件,在jar的情况下将不可用。因此,我需要另一种方法来获取资源目录的绝对路径。我必须将其传递给File.walk API来查找子目录和文件。

2个回答

8

正如问题中所提到的,首先我想要获取confX目录,然后读取conf.txt文件。

最终,我可以按照以下方式解决我的问题。

ClassLoader cl = this.getClass().getClassLoader();
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
try {
        Resource resources[] = resolver.getResources("classpath:Conf/*/");
} catch (IOException e) {
        e.printStackTrace();
}

这将会给出Conf目录的所有子目录。这里classpath:Conf/*/末尾的/非常重要。如果我们不加/,它会正常工作但在jar包中不起作用。从上面的代码块中,resources[]数组将包含类似于class path resource [Conf/conf1/]等的目录位置。我需要子目录名称以读取相应的文件。以下是相关代码。
Arrays.asList(resources).stream()
                        .forEach(resource ->{ 
                                  Pattern dirPattern = Pattern.compile(".*?\\[(.*/(.*?))/\\]$");
                                  if (resource.toString().matches(".*?\\[.*?\\]$")) {
                                      Matcher matcher = dirPattern.matcher(resource.toString());
                                     if (matcher.find()) {
                                        String dir = matcher.group(1);
                                        readFile(dir);
                                      }
                                  }
                             });


public void readFile(String dir)
{

   ClassPathResource classPathResource = new ClassPathResource(dir+ "/conf.txt");
    try (BufferedReader fileReader = new BufferedReader(
            new InputStreamReader(classPathResource2.getInputStream()))) {
        fileReader.lines().forEach(data -> System.out.println(data));
     }catch (IOException e) {
        e.printStackTrace();
    }
}

我需要将每个txt文件映射到其对应的目录。这就是我选择这种方式的原因。如果你只需要获取文件并读取它们,可以像下面这样做。这将列出Conf目录下的所有内容。

 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
try {
        Resource resources[] = resolver.getResources("classpath:Conf/**");
} catch (IOException e) {
        e.printStackTrace();
}

0
尝试以下代码。它可以扫描最多n层的所需文件,可以使用以下代码中的maxDepth变量进行指定。
// Finding a file upto x level in File Directory using NIO Files.find
    Path start = Paths.get("/Users/***/Documents/server_pull");
    int maxDepth = 5;
    try(Stream<Path> stream = Files.find(start, 
                                        maxDepth, 
                                        (path, attr) -> String.valueOf(path).endsWith(".txt"))){
        String fileName = stream
                            .sorted()
                            .map(String::valueOf)
                            .filter((path) -> {
                                //System.out.println("In Filter : "+path);
                                return String.valueOf(path).endsWith("config.txt");
                            })
                            .collect(Collectors.joining());
        System.out.println("fileName : "+fileName);
    }catch(Exception e){
        e.printStackTrace();
    }

另一种方法是使用Files.walk方法,如下所示:

// Finding a file upto x level in File Directory using NIO Files.walk

    Path startWalk = Paths.get("/Users/***/Documents/server_pull");
    int depth = 5;
    try( Stream<Path> stream1 = Files.walk(startWalk, 
                                            depth)){
        String walkedFile = stream1
                            .map(String::valueOf)
                            .filter(path -> {
                                return String.valueOf(path).endsWith("config.txt");
                            })
                            .sorted()
                            .collect(Collectors.joining());
        System.out.println("walkedFile = "+walkedFile);

    }catch(Exception e){
        e.printStackTrace();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接