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.
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);
}
}
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)
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
No need to do this. File.mkdirs() instead
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With