`java.nio.file.Path`- necessary to `path = Files.createDirectories(path)`? - java

Talking about the Java java.nio.file.Path and associated utilities.
As the title suggests, is it really necessary for one to set the path they just created?
I.E,
Path path = Path.of("some", "dir");
path = Files.createDirectories(path);
//continue to use path variable
vs
Path path = Path.of("some", "dir");
Files.createDirectories(path);
//continue to use path variable
Is the second example adequate, or are there actually changes made that are relevant/ required that are returned in the Path object in createDirectories?

Related

Add a file name to a Path object

I have a Path object leading to a folder.
Path pathToFolder = Paths.get( "/Users/someuser/" );
…or the recommended way using Path.of:
Path pathToFolder = Path.of( "/Users/someuser/" );
I want to create a file named "whatever.text" in that folder using Files.newBufferedWriter where I pass a Path object.
BufferedWriter writer = Files.newBufferedWriter( pathToFile ) ;
How do I transform my pathToFolder to get a Path object pathToFile?
I need more than mere string manipulation, as these are soft-coded values determined at runtime. And I am trying to be cross-platform as well.
This seems like an obvious question, but I could not find any existing post (the terminology does make searching tricky).
You are looking for Path.resolve():
Converts a given path string to a Path and resolves it against this Path in exactly the manner specified by the resolve method. For example, suppose that the name separator is "/" and a path represents "foo/bar", then invoking this method with the path string "gus" will result in the Path "foo/bar/gus".
So you should use this:
Path pathToFolder = Path.of("/Users/someuser/");
Path pathToFile = pathToFolder.resolve("your-file-name");
BufferedWriter writer = Files.newBufferedWriter(pathToFile);

How to program relative path from string in Java

I have the following problem. I am writing a program that imitates Windows Command prompt. For example user enters: cd C:\\Intel and in my code I solve it like this:
setCurrentPath(Paths.get(string));
where setCurrentPath is a method which sets the current path to the one which is entered (string). My problem is that, how can I set new path if the entered path is relative. For example, if I am currently in C:\\Intel and user wants to go to C:\\Intel\\Logs and enters: cd Logs (instead of C:\\Intel\\Logs). I suppose there are some methods build in Java which can help me out but I am learning Java only a few months so I am unaware of them. Be aware that I threat path as a string.
You could test if path from user is absolute or not and based on result either set it directly, or use Path.resolve.
DEMO:
Path currentPath = Paths.get("C:\\projects\\project1");
String pathFromUser = "..\\project2";
Path userPath = Paths.get(pathFromUser);
if (userPath.isAbsolute()){
currentPath = userPath;
}else{//is relative
currentPath = currentPath.resolve(userPath).normalize();
}
System.out.println(currentPath);
Output: C:\projects\project2
Use the isAbsolute() method to check the input and then use the resolvePath if the isAbsolute() method returns false.
https://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#isAbsolute()
The reason why you have to check if the path is absolute first is described below for the resolve method:
Path resolve(Path other)
Resolve the given path against this path. If the other parameter is an
absolute path then this method trivially returns other. If other is an
empty path then this method trivially returns this path. Otherwise
this method considers this path to be a directory and resolves the
given path against this path. In the simplest case, the given path
does not have a root component, in which case this method joins the
given path to this path and returns a resulting path that ends with
the given path. Where the given path has a root component then
resolution is highly implementation dependent and therefore
unspecified.
https://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#resolve(java.nio.file.Path)

Getting relativePath and then diving deeper

I have a package structure like
A
|_B
|_C
|_D
|_"myFile.txt"
myMain.java
In my main i want to do something like
Path currentRelativePath = Paths.get("");
Which gives me the current relative path to where my Main() is located. Something along the lines of /home/myprojects/project1/src/ How do I amend the above to get me the relative path all the way down to the level of myFile.txt?
I have tried things like:
Path currentRelativePath = Paths.get("" + "/B/C/D/");
and
Path currentRelativePath = Paths.get("","B/C/D/");
and
Path currentRelativePath = Paths.get("");
Path finalPath = Paths.get(currentRelativePath.toString(),"/B/C/D/");
But in each case it only gets the "/B/C/D/" portion and not the beginning of the path.
//Gets from the current working directory a path to B/C/D
Path path = Paths.get("B/C/D");
//String equal to "B/C/D"
path.toString();
//String equal to "/home/myprojects/project1/src/B/C/D"
path.toAbsolutePath().toString();
I think you are confusing relative and absolute paths. /home/myprojects/project1/src/ is an absolute path, not as you say in your question "the current relative path"

Why does Path class allow file within a file?

I'm playing around with the NIO Path stuff, and came across this quesion:
What will the following code fragment print?
Path p1 = Paths.get("\\personal\\readme.txt");
Path p2 = Paths.get("\\index.html");
Path p3 = p1.relativize(p2);
System.out.println(p3);
The answer is
..\..\index.html
But this would make the entire Path:
\personal\readme.txt\index.html
This looks like nonsense to me, as you can't put a file within a file like this. Can you?
If readme.txt were a directory instead of a file, I would be perfectly OK with this, but I'm very confused as to why it allows a filepath like this to exist?
Or is there some weird way that you can actually do this?
Both ISOs and Zip files (therefore JAR/WAR/XUL/CHM...) represent files that can contain a folder structure of files. These files can be handled either as a file, or as a folder; both are legitimate uses for them. Therefore, this would be semantically meaningful:
Path p1 = Paths.get("\\personal\\photos.zip");
Path p2 = Paths.get("\\family\\me.png");
Path p3 = p1.relativize(p2);
System.out.println(p3);"
While I am not aware of any implementations in Java that behave this way, it is a semantic used in XUL and Windows Explorer.
The result is ..\..\index.html
From the javadoc:
This method attempts to construct a relative path that when resolved
against this path, yields a path that locates the same file as the
given path. For example, on UNIX, if this path is "/a/b" and the given
path is "/a/b/c/d" then the resulting relative path would be "c/d".
Where this path and the given path do not have a root component, then
a relative path can be constructed.
This means that you would have to go up two folders from this path to reach a path from which you can reach your given path, index.html.
Remember, these are all paths, not actual files/file descriptors.
Path p1 = Paths.get("\\personal\\readme.txt");
Path p2 = Paths.get("\\personal\\index.html");
Path p3 = p1.relativize(p2);
System.out.println(p3);
prints ..\index.html, meaning from \\personal\\readme.txt, go up one and then access index.html.

java.nio.Path relativize between Paths does assumptions, which I cannot check

I am using the new Path object of java 7 and I am running into an issue.
I have a file storage system with a base directory and I create my own relative path. In the end I want to store just this relative path somewhere. I am running into a problem with Path.relativize though.
I have two usecases.
1.
Path baseDir = Paths.get("uploads");
Path filename = Paths.get("uploads/image/test.png")
return baseDir.relativize(filename);
This returns a Path image/test.png, which is perfect.
However, usecase 2:
Path baseDir = Paths.get("uploads");
Path filename = Paths.get("image/test.png")
return baseDir.relativize(filename);
returns ../image/test.png. I just want it to return "image/test.png"
In the Path tutorial it says
In the absence of any other information, it is assumed that 2 Paths are siblings
What I want is to be able to detect that this is the case. In this case, I want to just return the filename and ignore the baseDir.
I currently solve it like this, but I was hoping there was a better way:
Path rootEnding = getRootDirectory().getName(getRootDirectory().getNameCount() - 1);
for (Path part : path) {
if (part.equals(rootEnding)) {
return getRootDirectory().relativize(path);
}
}
return path;
So my question is, is there any better way of checking this?
Try adding a normalize() after relativize(). It seems to intended to do exactly this (remove unnecessary .. and . ). Don't miss the caution about symlinks in the javadoc.
This isn't 100% equivalent to what you wrote above, but I think it does what you want. Basically, let baseDir be a relative path. Pretend that whatever baseDir is relative to is the root of the file system. Then allow filename to be either relative or absolute from this "simulated root".
What about:
if (filename.startsWith(baseDir)) {
filename = baseDir.relativize(filename);
}

Categories

Resources