如何实现跨平台的路径分割?

21
我使用以下代码从给定路径中获取包含所有子目录的数组。
String[] subDirs = path.split(File.separator); 

我需要这个数组来检查特定文件夹是否在此路径的正确位置。

这看起来是一个好的解决方案,直到findBugs抱怨File.separator被用作正则表达式。似乎将Windows文件分隔符传递给正在构建正则表达式的函数是一个坏主意,因为反斜杠是转义字符。

如何以跨平台的方式拆分路径而不使用File.separator?

或者像这样的代码可以吗?

String[] subDirs = path.split("/"); 
6个回答

45

转义正则表达式中的特殊字符

如果您需要将任意String作为正则表达式模式并将其转义,使用Pattern.quote

根据API文档:

public static String quote(String s)

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

参数: s - 要转义的字符串
返回: 包含字面替换的字符串

这意味着你可以这样做:

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

将替换字符串文本化

如果你需要将任意的替换字符串文本化,可以使用Matcher.quoteReplacement

以下是该方法API的说明:

public static String quoteReplacement(String s)

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

参数: s - 要进行文本化的字符串
返回值: 字面字符串替换

这个被引用的替换字符串同样适用于String.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"

17

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

不建议使用path.replaceAll("\\", "/").split("/")的方式。


+1 有一些不正规的方法可以做到这一点,也有一些正规的方法可以做到。这是正确的方法,与使用'/'、''或其他你完全忘记的操作系统特定字符相比,它将为你节省很多痛苦。 - ShuggyCoUk
是的,我走了一条令人沮丧的路线。抱歉。 - akarnokd

4
创建一个空列表,使用forEach迭代路径元素并将每个元素插入列表中以备后用:
List<String> pathElements = new ArrayList<>();
Paths.get("/foo/bar/blah/baz").forEach(p -> pathElements.add(p.toString()))

此外,如果您需要使用特定的路径元素,请使用以下方法:
<pathObject>.getName(<intIndex>).toString() 

如果你需要将路径的多个部分返回为字符串,可以使用以下代码:<pathObject>是通过调用Paths.get()返回的。

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

您可以使用以下代码获取路径元素的总数(用于<intEnd>):

<pathObject>.getNameCount()

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


请添加解释您的代码如何工作以及如何解决问题的说明。 - Gergely Toth
如果提供了解决方案,请提供解释,否则答案将被删除。 - Ashish Ratan

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可以用于类似的目的。


0

您可以使用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;
}

-3

关于什么?

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

问题说是跨平台的,但你的只能在Windows上运行。 - kaiser

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