Java:如何获取路径的各个部分

5
这应该很简单,但我卡住了。假设你有路径/a/b/c/。我想将其转换为包含以下内容的数组:
  • /
  • /a/
  • /a/b/
  • /a/b/c/
开头和结尾的斜杠是可选的。 有谁能帮忙吗?
我要用它来创建一个目录的函数,并且我想要它创建所有缺少的部分,如果例如ab不存在,也不会失败。

更新: 当然,如果可以的话,我会使用 File.mkdirs(),但这不是在本地文件系统上。它是为了简化与仅具有以字符串形式接受路径的mkdir方法的SFTP库进行交互。


如下两个回答所述,File.mkdirs() 是正确的方式。然而,如果您非常坚持手动创建,可以使用 split("//") 来分割路径,然后用 for 循环实现:String[] bits = path.split("//"); File f = null; for(int i=0;i<bits.length;i++){ if(f = null) f = new File(bit[i]); else f = new File(f, bits[i]); f.mkdir(); } - Femi
6个回答

11

为什么不直接使用 File.mkdirs() 呢?


编辑:根据您的要求不使用File.mkdirs():

我仍然认为使用File作为辅助类更容易:

package com.example.test;

import java.io.File;
import java.util.LinkedList;
import java.util.List;

public class FileSplitter {
    final private File path;

    public List<String> getPathStrings()
    {
        LinkedList<String> list = new LinkedList<String>();
        File p = this.path;
        while (p != null)
        {
            list.addFirst(p.getPath());
            p = p.getParentFile();
        }
        return list;
    }

    public FileSplitter(File path) { this.path = path; }

    public static void main(String[] args) {
        doit(new File("/foo/bar/baz"));
        doit(new File("/bam/biff/boom/pow"));
    }

    private static void doit(File file) {
        for (String s : new FileSplitter(file)
                .getPathStrings())
            System.out.println(s);      
    }
}

在我的电脑上(windows系统),这将打印出以下内容:
\
\foo
\foo\bar
\foo\bar\baz
\
\bam
\bam\biff
\bam\biff\boom
\bam\biff\boom\pow

如果您无论如何都需要使用正斜杠,那么我建议使用字符串而不是文件进行实现,或者在使用时执行.replace('\\','/')


最后,这里有一种方法可能对您的最终应用程序更有帮助。

它与之前的输出相同,但适合于控制反转的倒置, 在其中,您可以执行自定义的mkdir()作为伪Runnable传递为路径迭代器的步骤:

package com.example.test;

import java.io.File;

public class PathRunner
{
    final private File path;
    public PathRunner(File path) { 
        this.path = path; 
    }

    public interface Step
    {
        public boolean step(File path);
    }

    public boolean run(Step step) 
    {
        return run(step, this.path);
    }
    private boolean run(Step step, File p)
    {
        if (p == null)
            return true;
        else if (!run(step, p.getParentFile()))
            return false;
        else
            return step.step(p);
    }

    /**** test methods ****/

    public static void main(String[] args) {
        doit(new File("/foo/bar/baz"));
        doit(new File("/bam/biff/boom/pow"));
    }
    private static boolean doit(File path) {
        Step step = new Step()
        {
            @Override public boolean step(File path) {
                System.out.println(path);
                return true;
                /* in a mkdir operation, here's where you would call: 

                return yourObject.mkdir(
                    path.getPath().replace('\\', '/')
                );
                 */
            }               
        };
        return new PathRunner(path).run(step);
    }
}

在回答中补充说明了为什么我不能使用它。应该一开始就提到了,我的错。 :9 - Svish
有点让它正常运行了。但是它却破坏了斜杠,这并不好。 - Svish
部分地翻译以下与编程有关的内容:仅翻译文本。不要相信它将保留潜在的开头和结束斜杠。如果能够避免,我也不想这样做 :) - Svish

5
如果您需要一些原始的东西,请尝试使用split和append。
public class StackOverflow {

    public static void main(String args[]) {

        String[] folders = "/a/b/c/".split("/");
        String[] paths = new String[folders.length];
        String path = "";

        for (int i = 0; i < folders.length; i++) {
            path +=   folders[i] + "/";
            paths[i] = path;
        }
    }
}

这是代码块的输出结果:

run:
/
/a/
/a/b/
/a/b/c/
BUILD SUCCESSFUL (total time: 0 seconds)

简单而且似乎有效。但是如果开头或结尾没有 / 呢?从我所看到的,即使没有任何斜杠,它也会在结尾添加一个斜杠。 - Svish
@Svish,你说的角落情况是对的,但这段代码只是一个概念验证,让你有个想法。你可以改进它来处理角落情况,或者强制用户输入带前导和尾随斜杠的路径。 - Kerem Baydoğan

4
文件类支持此功能。
public static void main(String... args) {
    split(new File("/a/b/c/d/e"));
    split(new File("\\A\\B\\C\\D\\E"));
}

private static void split(File file) {
    File parent = file.getParentFile();
    if (parent != null) split(parent);
    System.out.println(file);
}

在Windows上打印
\
\a
\a\b
\a\b\c
\a\b\c\d
\a\b\c\d\e
\
\A
\A\B
\A\B\C
\A\B\C\D
\A\B\C\D\E

2

2

最终得到了这段代码:

   public String[] componizePath(String path)
   {
      ArrayList<String> parts = new ArrayList<String>();  

      int index = 0;
      while(index < path.length())
      {
         if(path.charAt(index) == '/' || index == path.length()-1)
         {
            parts.add(path.substring(0, index+1));
         }
         index++;
      }

      return parts.toArray(new String[0]);
   }

JUnit测试:

   @Test
   public void componizePath_EmptyPath()
   {
      String[] actual = getSftp().componizePath("");
      String[] expected = new String[0];
      assertArrayEquals(expected, actual);
   }

   @Test
   public void componizePath_RootPath()
   {
      String[] actual = getSftp().componizePath("/");
      String[] expected = new String[] {"/"};
      assertArrayEquals(expected, actual);
   }

   @Test
   public void componizePath_SimplePath()
   {
      String[] actual = getSftp().componizePath("a");
      String[] expected = new String[] {"a"};
      assertArrayEquals(expected, actual);
   }

   @Test
   public void componizePath_SimplePathWithTrailingSlash()
   {
      String[] actual = getSftp().componizePath("a/");
      String[] expected = new String[] {"a/"};
      assertArrayEquals(expected, actual);
   }

   @Test
   public void componizePath_ComplexerPath()
   {
      String[] actual = getSftp().componizePath("a/b/cc");
      String[] expected = new String[] {"a/", "a/b/", "a/b/cc"};
      assertArrayEquals(expected, actual);
   }

   @Test
   public void componizePath_ComplexerPathWithTrailingSlash()
   {
      String[] actual = getSftp().componizePath("a/b/c/");
      String[] expected = new String[] {"a/", "a/b/", "a/b/c/"};
      assertArrayEquals(expected, actual);
   }

   @Test
   public void componizePath_ComplexerPathWithLeadingSlash()
   {
      String[] actual = getSftp().componizePath("/a/b/c");
      String[] expected = new String[] {"/", "/a/", "/a/b/", "/a/b/c"};
      assertArrayEquals(expected, actual);
   }

0

这应该是一个相当简单的算法,如果你有一个字符串路径 = "/a/b/c/",你可以执行以下操作:

def f(st):
    index = 0
    array = []
    while index < len(st):
        if(st[index] == '/'):
            array += [st[:index+1]]

        index += 1
    return array

这是一个Python算法,你可以很容易地将其转换为Java。当然,你可以使用Jason和I82Much指出的File.mkdirs(),但看到算法如何工作也很有趣。

编辑 在Java中,你不能迭代字符串,但你可以将字符串转换为字符数组列表,当你迭代时,编写条件,如果字符是'/',则创建一个新字符串,将从第一个字符到当前找到的字符(应该是'/')连接起来,并将其添加到之前初始化的字符串列表中。得到的字符串列表就是你需要的列表。 如果你自己尝试并看看效果,那么这对你来说是很好的练习。当然,你也可以迭代结果列表并创建目录。


array += [st[:index+1]] 这段代码是做什么的?我猜它会向数组中添加另一个元素,但具体是什么呢? - Svish
@Svish:st[:index + 1] 是 Python 的语法,表示字符串从 0 到 index 的部分,例如如果 st = "abcdef",那么 st[:3] = "abc"。希望这能帮到你。 - Saher Ahwal

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