【问题标题】:Read files from sub directories of class path resource folder in spring boot在spring boot中从类路径资源文件夹的子目录中读取文件
【发布时间】:2019-01-29 11:51:47
【问题描述】:

我想从资源文件夹的子目录中读取文件。 我遇到了 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 才能找到子目录和文件。

【问题讨论】:

    标签: java maven spring-boot


    【解决方案1】:

    如问题中所述,首先我想获取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/] and so on 这样的目录位置。我需要子目录名来读取相应的文件。这是它的代码。

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

    【讨论】:

      【解决方案2】:

      试试下面的代码。它可以扫描所需的文件最多 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();
          }
      

      【讨论】:

        猜你喜欢
        • 2020-07-21
        • 2017-11-08
        • 1970-01-01
        • 1970-01-01
        • 2010-12-02
        • 1970-01-01
        • 2018-12-19
        • 1970-01-01
        • 2019-10-16
        相关资源
        最近更新 更多