【问题标题】:How to split a path platform independent?如何独立拆分路径平台?
【发布时间】:2018-06-08 23:36:17
【问题描述】:

我正在使用以下代码从给定路径获取包含所有子目录的数组。

String[] subDirs = path.split(File.separator); 

我需要该数组来检查某些文件夹是否位于此路径中的正确位置。 在 findBugs 抱怨 File.separator 被用作正则表达式之前,这看起来是一个很好的解决方案。似乎将 windows 文件分隔符传递给正在从中构建正则表达式的函数是一个坏主意,因为反斜杠是转义字符。

如何在不使用 File.separator 的情况下跨平台拆分路径? 或者这样的代码可以吗?

String[] subDirs = path.split("/"); 

【问题讨论】:

    标签: java regex file cross-platform


    【解决方案1】:

    文字化模式字符串

    当您需要将任意String 字面化以用作正则表达式模式时,请使用Pattern.quote

    来自 API:

    public static String quote(String s)

    为指定的String 返回文字模式String。此方法生成一个String,可用于创建一个Pattern,它与字符串s 匹配,就好像它是一个文字模式一样。 输入序列中的元字符或转义序列将没有特殊含义。

    参数: s - 要文字化的字符串
    返回: 文字字符串替换

    这意味着您可以执行以下操作:

    String[] subDirs = path.split(Pattern.quote(File.separator));
    

    文字化替换字符串

    如果您需要文字化任意替换 String,请使用 Matcher.quoteReplacement

    来自 API:

    public static String quoteReplacement(String s)

    为指定的String 返回文字替换String。此方法生成一个String,它将作为Matcher 类的appendReplacement 方法中的s 的文字替换。生成的String 将匹配s 中被视为文字序列的字符序列。斜杠 ('\') 和美元符号 ('$') 将没有特殊含义。

    参数: s - 要文字化的字符串
    返回: 文字字符串替换

    这个引用的替换StringString.replaceFirstString.replaceAll 中也很有用:

    请注意,替换字符串中的反斜杠 (\) 和美元符号 ($) 可能会导致结果与将其视为文字替换字符串时不同。如果需要,请使用 Matcher.quoteReplacement 隐藏这些字符的特殊含义。


    示例

        System.out.println(
            "O.M.G.".replaceAll(".", "!")
        ); // prints "!!!!!!"
    
        System.out.println(
            "O.M.G.".replaceAll(Pattern.quote("."), "!")
        ); // prints "O!M!G!"
    
        System.out.println(
            "Microsoft software".replaceAll("so", "$0")
        ); // prints "Microsoft software"
    
        System.out.println(
            "Microsoft software".replaceAll("so", Matcher.quoteReplacement("$0"))
        ); // prints "Micro$0ft $0ftware"
    

    【讨论】:

      【解决方案2】:

      重复使用path.getParentFile() 来获取路径的所有组件。

      不鼓励的方式是path.replaceAll("\\", "/").split("/")

      【讨论】:

      • +1 有一些 hacky 方法可以做到这一点,并编写方法来做到这一点。这是正确的方法,与使用“/”、“\”、 拆分相比,这将为您省去很多痛苦
      • 是的,我采取了令人沮丧的方式。对不起。
      【解决方案3】:

      java.nio.file.Path 实现了Iterable<Path>,所以你可以这样做:

      public static void showElements(Path p) {
          List<String> nameElements = new ArrayList<>();
          for (Path nameElement: p)
              nameElements.add(nameElement.toFile().getName());
          System.out.printf("For this file: [%s], the following elements were found: [%s]\n"
                            , p.toAbsolutePath()
                            , Joiner.on(", ").join(nameElements));
      }
      

      方法getNameCountgetName 可用于类似目的。

      【讨论】:

        【解决方案4】:

        创建一个空列表并使用 forEach 遍历路径元素,将每个元素插入列表以供以后使用:

        List<String> pathElements = new ArrayList<>();
        Paths.get("/foo/bar/blah/baz").forEach(p -> pathElements.add(p.toString()))
        

        此外,如果您需要特定的路径元素,请使用:

        <pathObject>.getName(<intIndex>).toString() 
        

        其中&lt;pathObject&gt; 由对Paths.get() 的调用返回,如果您需要在字符串中返回路径的多个部分,请使用:

        <pathObject>.subPath(<intStart>, <intEnd>).toString()
        

        您可以通过以下方式获取路径元素的总数(用于&lt;intEnd&gt;):

        <pathObject>.getNameCount()
        

        在 Java PathPaths 文档页面中还有其他有用的方法。

        【讨论】:

        • 请添加解释为什么您的代码有效以及它如何解决问题中的问题
        • 如果给出解决方案,请提供解释,否则答案将被删除。
        【解决方案5】:

        可以使用Path接口:

        Path p = Paths.get(pathStr);
        for (int i = 0; i < p.getNameCount(); i++) {
            String name = p.getName(i).toString();
            //do what you need with name;
        }
        

        【讨论】:

          【解决方案6】:

          怎么样

          String[] subDirs = path.split(File.separator.replaceAll("\\", "\\\\"));
          

          【讨论】:

          • 问题说跨平台,你的只适用于windows。
          猜你喜欢
          • 1970-01-01
          • 2021-04-03
          • 1970-01-01
          • 1970-01-01
          • 2012-12-19
          • 2016-03-24
          • 2014-09-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多