I'm looking at some sample code for creating a File in Java:
File f = new File("test/.././file.txt");
I'm confused at how this works - how can you have "test" , and then those .. and . in between like that? If I run this code in an arbitrary directory in my machine, why does it work(i.e I don't have a folder called "test" ).
this is part of some code for Path-Testing in java(getAbsolutePath() and etc)
thanks
The .. just means "up a directory level". The single . just means "current directory level". Why they are in your file path is beyond me. Your path seems to mean "go into the test folder, then go up a level (to the one you started in), stay in that level, then look for file.txt". You could do the same thing with just new File("file.txt").
File f = new File("test/.././file.txt"); //.. is used to go one hierarchy above in the directory structure and . is for current directory
suppose you have directory structure like ABC/test/file.txt
and if you are inside test then your . is path upto test
and .. is path upto ABC as .. represents parent directory and parent of "test" is "ABC"
the .. denote a parent directory; . denote this directory.
Having this as valid is another good reason why you should use getCanonicalPath() vs getAbsolutePath()
For example:
Lets say your file is under /folder1/folder2 directory
then
File f = new File("/folder1/folder2/folder3/../<your file>");
f.getCanonicalPath() ==> /folder1/folder2/<your file>
f.getAbsolutePath() ==> /folder1/folder2/folder3/../<your file>
Because the .. goes back up the directory hierarchy, so you'll be back to where you started (not in test). This is unnecessary as it's equivalent to:
File("test.txt")
And so should work regardless of which directory you run it in.
The ".." will go up one directory from the current directory. So, this code is basically the same as new File("./file.txt");
./ goes to the directory where your project is located
../ Goes back a folder lets say you have a resource directory
Res/graphics/sprites/image.png
If you do File file = new File("./graphics/sprites/);
That will point to the sprites directory
Now if you want to go back a file dir File newFile = file + "../";
Related
I'm copy files from a jar to a local folder.
The jar is located at a/b.
The folder (in the jar) I'm trying to extract is located at b/c
The destination folder should be z, i.e. a/b/c/x -> z/x
When I use c.relativize("x") I get ../c/x instead of x.
This is a problem when I then try to do: z.resolve(c.relativize(x)).
I get z/../c/x instead of z/x
How do I fix this issue?
I tried z.resolve(c.relativize(x).normalise()) but get the same result
The jar is b in the folder a. c is a resource (folder) inside the jar b. x is a file inside the folder c.
The jar is in folder A/B/
The source folder path inside the jar is /b/c/ with file /b/c/xxx.yyy
The destination folder is Z
The destination file should have path: Z/xxx.yyy
So:
Path sourceZip = Paths.get("/A/B/my.zip");
URI sourceZipURI = URI.create("jar:" + sourceZip.toUri());
Path targetFolder = Paths.get("/Z");
Map<String, Object> senv = new HashMap<>();
try (FileSystem sourceZipFS = FileSystems.newFileSystem(sourceZipURI, senv, null)) {
Path folderInZip = sourceZipFS.getPath("/b/c");
Files.list(folderInZip).forEach(p -> {
Path target = targetFolder.resolve(folderInZip.relativize(p).toString());
try {
Files.createDirectories(target.getParent());
Files.copy(p, target);
} catch (IOException e) {
e.printStackTrace();
}
});
}
The main issue was the reversal of relativize; not the first time I encountered the misunderstanding. child.relativize(parent) gives a .. whereas parent.relativize(child) truncates the path.
To get the target path one needs to convert the source Path to a string, to prevent combining two different file systems.
(I did not take care of subdirectories.)
I think you have misunderstood the usage of path.relativize(Path)
According to https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/file/Path.html#relativize(java.nio.file.Path), there is a statement as below:
Constructs a relative path between this path and a given path.
e.g.
Path pathA = Paths.get("a"); // i.e. /a or /anyDir/anySubDir/a
Path pathB = Paths.get("b"); // i.e. /b or /anyDir/anySubDir/b
pathA.relativize(pathB)
Assume the result is ../b, what does it mean?
It is actually telling you: as you are inside directory a, if you want to access directory b, you need to access by this approach cd ../b.
relativize(Path) is helping to analyzing the relative path between the parent Path and the child Path (i.e. how to access from parent Path to child Path).
Alternatively, from your question, looks like you are preferring to "construct" the path instead of "analyzing" the relative path. relativize(Path) is not the one for this purpose.
So, which one, "construct" manually or "analyze", do you want to achieve?
I try to move a file from one directory to another.
I do this with
File fileToMove = new File("/Users/kai-dj/separator_problem/from/file_to_move.file");
File destDir = new File("/Users/kai-dj/separator_problem/to");
if (fileToMove.exists() && destDir.isDirectory()) {
fileToMove.renameTo(new File(destDir.getAbsolutePath()+File.pathSeparator+fileToMove.getName()));
}
I'd expect to find file_to_move.file in folder /Users/kai-dj/separator_problem/to after execution, but I get a file named to/file_to_move.file placed in the parent folder /Users/kai-dj/separator_problem. At least that's what Finder shows.
As I thought: "File names mustn't contain path separator characters, this can't be true.", I also checked what ls would output in terminal:
mac-book:separator_problem kai-dj$ ls
from to:file_to_move.file
to
OK – seems no /in file name. Very strange nontheless.
Why does Finder show it as file name containing /?
Why does Java rename the file to <dirname>:<filename> – especially even when I used File.pathSeparator, not / and certainly not :?
I also tried with Files.move – same result.
EDIT: Solved, but I'd still love to know, why Finder shows : as / ^^
As mentioned in the comment above, the correct member to use is called File.separator.
Also, you can avoid using File.separator in general, and use Paths instead:
System.out.println(Paths.get("/Users/kai-dj/separator_problem/to", fileToMove.getName()).toAbsolutePath());
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.
In my app, I used this code:
File DirectoryPath = cw.getDir("custom", Context.MODE_PRIVATE);
While creating a directory, and it returns:
/data/data/com.custom/app_custom**
So my question is why this app_ appears along with directory name. I know its default, but what actually it means?
And secondly, how can I create a sub-directory inside my directory i.e. app_custom in this case. if anyone knows please help me to understand this concept of getDir.
As far as I think, automatic "app_" added to user created data folders avoid any conflicts with system predefined application folders (folders inside application data folder i.e. cache, contents, databases etc. which are automatically created).
One method to create a sub folder inside those "app_..." folders, get absolute path of "app_..." folder, append required folder name to that and create using mkdirs()
e.g.
File dir = new File(newFolderPath);
dir.mkdirs()
Note: sub folders do not get "app_..." prefix
You can create a new Directory using the path that you are getting from getDir(),
File file = getDir("custom", MODE_PRIVATE);
String path = file.getAbsolutePath();
File create_dir = new File(path+"/dir_name");
if(!create_dir.exists()){
create_dir.mkdir();
}
Basically, I have a directory with some files in it. In run configurations I am trying to put the directory as an arguement like so: \(workspacename\directory. Then, the following code should create a list of all the files in that directory:
String directory = args[1];
File folder = new File(directory);
File[] allFiles = folder.listFiles();
ArrayList<File> properFiles = null;
for (File file: allFiles) {
if(file.getName().endsWith(".dat")){
properFiles.add(file);
}
}
the problem i'm facing is that for some reason allFiles is null.
I'll take a guess at what your problem might be:
If your argument is a relative path (as opposed to an absolute path, staring with "/" or "c:/" for example), keep in mind that files will be relative to the working directory of the application.
So new File(directory) will be relative to wherever the application is started. In Eclipse the default working directory is in the project. So if your project is in the top level of the workspace, it will be something like workspacename/project.
You can try printing out folder.getAbsolutePath(), folder.exists() and folder.isDirectory() to help diagnose your problem.
The javadocs say listFiles() will return null if the directory does not actually exist (among other things):
Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.
Debug by verifying (debugger or printf) the args[1] value.
Also, it looks like you might be trying to use a substitution variable to insert the workspace location in the path. If so, again, you need to verify (via debugger or printf) that the placeholder is getting replaced properly.