【问题标题】:Case insensitive path startsWIth endsWith不区分大小写的路径startsWIthendsWith
【发布时间】:2018-03-29 01:44:14
【问题描述】:

传入的patternformat,考虑到它们都是小写的,我如何更改下面的sn-p 代码以便startsWithendsWith 返回true 如果模式和格式匹配大小写不敏感?

  try (Stream<Path> paths = Files.find(cobDir, 1,
            (path, attrs) -> attrs.isRegularFile()
                    && path.getFileName().startsWith(pattern)
                    && path.toString().endsWith(format))) {
        matchingFile = paths.findFirst();
    } catch (IOException e) {
        logger.error("Problem with getting files to process {}", e.getMessage());
    }

有没有比以下更漂亮的方法:

    try (Stream<Path> paths = Files.find(cobDir, 1,
            (path, attrs) -> attrs.isRegularFile()
                    && path.getFileName().toString().toLowerCase().startsWith(pattern)
                    && path.toString().toLowerCase().endsWith(format))) {
        matchingFile = paths.findFirst();
    } catch (IOException e) {
        logger.error("Problem with getting files to process {}", e.getMessage());
    }

【问题讨论】:

  • toUpperCase()toLowerCase() 路径的字符串和format
  • See this Q&A 剧透:不漂亮。

标签: java file path java-8


【解决方案1】:

startsWithendsWith 只是匹配字符串区域的特殊情况,也可以通过一般的regionMatches 方法处理:

  • string.startsWith(pattern) 可以替换为
    string.regionMatches(true, 0, pattern, 0, pattern.length())
  • string.endsWith(format) 可以替换为
    string.regionMatches(true, string.length()-format.length(), format, 0, format.length())

第一个参数参数 (true) 表示需要不区分大小写的匹配。

在第二种情况下,必须先将字符串存储到局部变量中,以便能够对其调用两个方法,这可能不太方便,但是,这仍然比将字符串转换为大写或小写并调用startsWithendsWith

首先,转换为 either(大写或小写)不足以处理所有字符以进行不区分大小写的匹配。正如the documentation of regionMatches 提到的,由于某些 Unicode 字符的不规则大小写映射,必须检查 both。当然,当您确定只处理 ASCII 或拉丁字符串时,这可能是不必要的。

另一方面,当您只想匹配开头或结尾的一个区域时,转换整个字符串的做法远远超出了必要的范围。特别是对于字符串大小首先排除匹配的情况。 regionMatches 首先检查这个。如果字符已经不匹配,它也不会执行大小写转换。

所以regionMatches 处理不规则大小写映射并且效率更高。

【讨论】:

    【解决方案2】:

    解决方案 1:不要测试大小写,只需将输入/测试值更改为小写并仅检查小写:-

    try (Stream<Path> paths = Files.find(cobDir, 1,
                (path, attrs) -> attrs.isRegularFile()
                        && path.getFileName().toLowerCase().startsWith(pattern)
                        && path.toString().toLowerCase().endsWith(format))) {
            matchingFile = paths.findFirst();
        } catch (IOException e) {
            logger.error("Problem with getting files to process {}", e.getMessage());
        }
    

    解决方案 2:将正则表达式(您尚未包含)更改为 not take case into account:-

    有没有更好的格式化方式,是的:-

    try (Stream<Path> paths = getPaths()){
    ...
    }
    

    并将所有丑陋的东西都放在一个函数中:-

    private Stream<Path> getPaths(/** cobDir, pattern, format */){
      return Files.find(cobDir, 1,
                  (path, attrs) -> attrs.isRegularFile()
                          &&
        path.getFileName().toString().toLowerCase().startsWith(pattern)
                          && path.toString().toLowerCase().endsWith(format))
    }
    

    【讨论】:

      【解决方案3】:

      使用String类toLowerCase()方法。 例如,

      Path p = new File("res.txt").toPath();
      

      p.toString.toLowerCase() ...... endsWith()startsWith(),您可以使用字符串参数的方法,因为 endsWith 和 startsWith 方法都重载了 2 个变体
      1) 作为路径类参数
      2) 作为字符串参数。

      【讨论】:

        【解决方案4】:

        我会为此使用不区分大小写的正则表达式

        final Pattern FILTER = Pattern.compile(
            Pattern.quote(pattern) + ".*" + Pattern.quote(format),
            Pattern.CASE_INSENSITIVE
        );
        Optional<Path> matchingFile = Files.find(cobDir, 1, (path, attrs) ->
                attrs.isRegularFile() && FILTER.matcher(path.toString()).matches()
            )
            .findFirst();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-06-06
          • 2021-11-16
          • 1970-01-01
          • 2010-09-28
          • 2019-10-12
          • 2021-02-27
          • 2011-10-06
          • 2021-04-29
          相关资源
          最近更新 更多