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

发布于 2024-11-14 05:24:06 字数 461 浏览 3 评论 0原文

这应该相当简单,但我只是卡住了。假设您有路径 /a/b/c/。我想将其转换为包含以下内容的数组:

  • /
  • /a/
  • /a/b/
  • /a/b/ c/

开头和结尾的斜线应该是可选的。有人愿意帮忙吗?

我将把它用于创建目录的函数,并且我希望它也创建所有缺失的部分,并且如果 ab 不这样做,也不会失败不存在。


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

This should be fairly simple, but I'm just stuck. Say you have the path /a/b/c/. I'd like to convert that into an array containing:

  • /
  • /a/
  • /a/b/
  • /a/b/c/

The slash at the beginning and the end should be optional. Any one care to help?

I'm going to use it for a function that creates a directory, and I want it to create all the missing parts too and not fail if for example a or b doesn't exist.


Update: I would of course use File.mkdirs() if I could, but this isn't on the local file system. It's to simplify interfacing with an SFTP library which only has a mkdir method taking a path in the form of a string.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

泅渡 2024-11-21 05:24:06

为什么不直接使用 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);
    }
}

Why not just use File.mkdirs()?


edit: per your requirement not to use File.mkdirs():

I still think it's easier to use File as a helper class:

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);      
    }
}

On my machine (windows) this prints out:

\
\foo
\foo\bar
\foo\bar\baz
\
\bam
\bam\biff
\bam\biff\boom
\bam\biff\boom\pow

If you have a need to use forward slashes no matter what, then I'd either implement using strings rather than Files, or just do a .replace('\\','/') on point of use.


Finally, here's an approach that might be more helpful for your end application.

It has the same output as the previous, but lends itself to an inversion of control
where you can perform your custom mkdir() as a pseudo-Runnable to be passed in as a step to a path iterator:

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);
    }
}
如果没结果 2024-11-21 05:24:06

如果你需要一些原始的东西。尝试拆分和追加。

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)

If you need something primitive. Try split and 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;
        }
    }
}

This the output of code block:

run:
/
/a/
/a/b/
/a/b/c/
BUILD SUCCESSFUL (total time: 0 seconds)
盛夏尉蓝 2024-11-21 05:24:06

File 类支持这一点。

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

The File class supports this.

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);
}

on windows prints

\
\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
谜泪 2024-11-21 05:24:06

无需这样做。 改为 File.mkdirs()< /a>

No need to do this. File.mkdirs() instead

盗心人 2024-11-21 05:24:06

最终得到以下代码:

   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);
   }

Ended up with this code:

   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 tests:

   @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);
   }
后来的我们 2024-11-21 05:24:06

这应该是一个相当简单的算法,如果给你一个字符串路径=“/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,您无法迭代字符串,但您可以将字符串转换为字符数组列表,并且当您迭代时,编写条件:如果字符是“/”,则创建一个连接的新字符串从第一个字符到当前字符的所有字符(我们发现应该是“/”),并将其添加到您之前初始化的字符串列表中。生成的字符串列表将是您需要的列表。
如果您自己尝试一下并看看效果如何,这对您来说是一个很好的实践。当然,您可以迭代结果列表并创建目录。

this should be a fairly simple algorithm, if your are given a string path = "/a/b/c/", you can do the following:

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

        index += 1
    return array

This is a python algorithm, you can easily convert that to Java. Of course you can use the File.mkdirs() that Jason and I82Much pointed out, but its also fun to see how the algorithm works.

EDIT
In the case of Java, you cannot iterate over a string, but you can covert the String into an arraylist of charachters, and when you iterate , you write the condition that if the charachter is '/', then create a new string that concatenates all the characters from the first till the current one we found which should be a '/', and add it to a String list you initialized earlier. The resulting string list will be the list you need.
It is good practice for you if you try it on your own and see how it goes. And of course you can iterate over the resulting list and make directories.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文