new File(parent, child) on Win32

In the javadoc for java.io.File, for the constructor File(File parent, String child) :

"If the child pathname string is absolute then it is converted into a relative pathname in a system-dependent way"

However, on win32 I can't replicate this behaviour. Take the case where parent is d:\test1, and child is d:\test2. Both are absolute. If the javadoc is correct, then the constructor above should recognise that d:\test2 is absolute, and convert it into a relative, i.e. ..\test2. But it doesn't:

File parent = new File("d:\\test1");

String child = "d:\\test2";

File file = new File(parent, child);

System.out.println(file.getAbsolutePath());

System.out.println(file.getPath());

Generates:

d:\test1\d:\test2

d:\test1\d:\test2

Whereas the javadioc says it should produce:

d:\test2

..\test2

This is on JDK 1.5.0_08 on win2k.

[915 byte] By [skaffmana] at [2007-11-26 19:11:23]
# 1

I think there is a misunderstanding here. On both Unix and Win platforms, FileSystem.resolve(String,String) method (which stays behind this constructor) simply converts child to a relative path by "eating" leading slash (or 2 slashes, on windows).

The behavior you was expecting is much more complex. Taking in consideration windows, API should decide how to build relative path based on:

1) child's drive

2) parent's type (regular file or directory)

3) ...

Example 1. Parent is a directory c:\path1 and child is d:\path2. There is no way to construct relative path in this situation

Example 2. Parent is a file d:\path1\fileA and child is d:\path2. Without checking parent type, you can get relative path like ..\..\path2, which is not correct. But checking its type requires that parent exists on file system. I think there is no need to implement such a complex logic in a simple constructor. Instead, application should care about this.

An algorithm could be like this:

1) on windows check drives, if differ simply return absolute path (child)

2) remove path prefixes (drives on windows, leading slashes on unix). For instance, C:\Projects\MS should be replaced with Projects\MS, the same on unix, /usr/local should be replaced with usr/local.

3) find common part of paths and remove it from both parent and child. This could be done in a number of ways.

4) For the rest of parent path replace each entry with "..". If parent path ends with / it is assumed to be a directory, otherwise try to check its type. If parent exist and is not a directory remove last entry (file name). Example: entry1\entry2\file should be replaced with "..\.."

5) Concatenate last result and the rest of child.

Any comments are greatly appreciated, I suggest to improve this scenario and to post implementation.

cebanencoa at 2007-7-9 21:08:34 > top of Java-index,Core,Core APIs...