Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different behaviour for Path.toFile() and new File(pathString)

I have mounted a network drive (samba server) in Windows.

I have a file in that drive that I wanted to read in a Java program.

Before I was trying to read the file using:

Paths.get(basePath, fileName).toFile()

But it was failing with error that file does not exists. The file was there and the path was good.

Then I tried the following code which worked:

String path = Paths.get(basePath, fileName).toAbsolutePath().toString()
File file = new File(path)

Is there any difference between both approaches? Does it require any security settings?

Update

So after I had used the second part (the one that worked), I went back to original (as it was) to verify debugging and this time it worked. I tried it with another file in same directory and it failed. It seems weird but I will check more.

like image 647
ata Avatar asked Oct 17 '22 19:10

ata


2 Answers

To best understand what is possibly happening I'd recommend debugging through the code. Below I'll explain what could be the issue based on my understanding of the source code.

First of all there is different implementations of Path and as you mentioned you're working on Windows so I had a look at the source code for WindowsPath which I found here.

So the method Path.toFile() is pretty simple. It is:

public final File toFile() {
    return new File(this.toString());
}

this is referring to the instance of the Path implementation and in the case of Windows it's an implementation of WindowsPath.

Looking at the WindowsPath class we see toString() implemented as follows:

@Override
public String toString() {
    return path;
}

Now looking at how this path variable is built. The WindowsPath class invokes the WindowsPathParser class which builds the path. The source for WindowsPathParser can be found here.

The parse method in WindowsPathParser is where you'll need to debug to find out exactly what is happening. Depending on your initial path that you pass as a method parameter this method parses that as a different WindowsPathType e.g. ABSOLUTE, DIRECTORY_RELATIVE.

The below code shows how the initial path input can change the type of WindowsPathType

Code

private static final String OUTPUT = "Path to [%s] is [%s]";

public static void main(String args[]) throws NoSuchFieldException, IllegalAccessException {
    printPathInformation("c:\\dev\\code");
    printPathInformation("\\c\\dev\\code");
}

private static void printPathInformation(String path) throws NoSuchFieldException, IllegalAccessException {
    Path windowsPath = Paths.get(path);

    Object type = getWindowsPathType(windowsPath);

    System.out.println(String.format(OUTPUT,path, type));
}

private static Object getWindowsPathType(Path path) throws NoSuchFieldException, IllegalAccessException {
    Field type = path.getClass().getDeclaredField("type");

    type.setAccessible(true);

    return type.get(path);
}

Output

Path to [c:\dev\code] is [ABSOLUTE]
Path to [\c\dev\code] is [DIRECTORY_RELATIVE]
like image 162
Garreth Golding Avatar answered Oct 19 '22 09:10

Garreth Golding


I would check your filepaths and maybe imports because this worked fine for me also not sure why your breaking up your path but maybe were talking about 2 different path imports

System.out.println("File:"+new File(path).exists());
System.out.println("Path:"+Paths.get(path).toFile().exists());

My imports if you want to compare

import java.io.File;
import java.nio.file.Paths;

I would say give it a shot with the full path not broken up at all see if anything changes

like image 33
Matt Avatar answered Oct 19 '22 10:10

Matt