Java - 正则表达式分割目录路径

5
我正在尝试在Java中实现以下功能:给定一个目录路径,如"/a/b/c",我想要得到一个字符串数组["a", "b", "c"]。代码如下:
private static final String DIRECTORY_PATH_SEPARATOR = "/";  
    Iterator iter = testPaths.iterator();

            String[] directories;

        while( iter.hasNext() ) {

            directories = ( ( String ) iter.next() ).split(DIRECTORY_PATH_SEPARATOR);
        }

但是我作为数组得到的也有空格。我想要获取所有长度大于0的字符串。
我该怎么做?

4个回答

4

如果路径以分隔符开头,那么(在有效路径中)唯一可能得到空字符串的地方是第一个项目。如果它有前导分隔符,请在不带它的路径上进行拆分。

String path = "/a/b/c";
String[] directories = path.substring(1).split(DIRECTORY_PATH_SEPARATOR);
// { "a", "b", "c" }

如OmnipotentEntity所指出的那样,我的有关有效路径的假设是错误的。否则,在使用split()时,您将不得不遍历数组并保留非空字符串。
String path = "/a/b////c";
String[] split = path.split(DIRECTORY_PATH_SEPARATOR);
ArrayList<String> directories = new ArrayList<String>(split.length);
for (String dir : split)
    if (dir.length() > 0)
        directories.add(dir);

另一种方法是使用实际的正则表达式来匹配非分隔符字符:

String path = "/a/b////c";
ArrayList<String> directories = new ArrayList<String>();
Pattern regex = Pattern.compile("[^" + DIRECTORY_PATH_SEPARATOR + "]+");
Matcher matcher = regex.matcher(path);
while (matcher.find())
    directories.add(matcher.group());

实际上并不是这样的:"/a//b//////c" 也是一个有效的路径。 - OmnipotentEntity
@Omni:那真的是一个有效的路径吗?如果是的话,我就得修改一下。 - Jeff Mercado
尝试在shell中自己运行,确保正确。 :) 可能最好的做法是在数组完成后遍历它并消除空字符串。 - OmnipotentEntity
@Omni:感谢你提醒。这是我不知道的。 - Jeff Mercado

3
你应该使用File类来完成这个任务,而不是使用正则表达式。

1

String.split(String) 方法不太灵活,而且其结果可能会令人惊讶(例如默默地丢弃空的尾随字符串)。我在所有项目中都使用 Guava 库(Google Core Libraries for Java),其中包含一个非常好用的 Splitter 工具,以一种非常易读和可预测的方式实现了您想要的功能:

String path = "/a/b///c///";
Iterable<String> directories = Splitter
    .on(DIRECTORY_PATH_SEPARATOR)
    .omitEmptyStrings()
    .split(path);

这将为您提供一个可迭代对象,您可以直接在for循环中使用,如下所示:

for(String directory : directories) {
  System.out.println(directory);
}

在这种情况下,它甚至不会创建一个中间对象来存储目录,而是动态创建它们。
如果您确实需要目录列表,可以将可迭代对象复制到ArrayList或数组中,如下所示:
List<String> dirList = Lists.newArrayList(directories);
String[] dirArray = Iterables.toArray(directories, String.class);

作为结束语:为了编写可移植的代码,您应该使用File.separator而不是DIRECTORY_PATH_SEPARATOR

0
这里有一个更可靠的非正则表达式版本,它使用了文件系统例程:
public static List<String> splitFilePath(final File f){
    if(f == null){
        throw new NullPointerException();
    }
    final List<String> result = new ArrayList<String>();
    File temp = f.getAbsoluteFile();
    while(temp != null){
        result.add(0, temp.getName());
        temp = temp.getParentFile();
    }
    return result;
}

测试代码:

public static void main(final String[] args){
    final File f = new File("foo/bar/phleem.txt");
    final List<String> parts = splitFilePath(f);
    System.out.println(parts);
}

输出:

[, home, seanizer, projects, eclipse, helios2, stackfiddler, foo, bar, phleem.txt]

我返回一个列表,因为它更易用,但是你也可以改变方法返回一个数组或者在外部使用以下方式转换结果:

List<String> parts = splitFilePath(f);
String[] partsAsArray = parts.toArray(new String[parts.size()]);

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