Page 1 of 2

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 30, 2016 1:43 am
by JavaNerd
Hi,

Could you help me make sense out of this:

Code: Select all

scala> val p1 = Paths.get("/personal/./photos/../readme.txt")
p1: java.nio.file.Path = /personal/./photos/../readme.txt

scala> val p2 = Paths.get("/personal/index.html")
p2: java.nio.file.Path = /personal/index.html

scala> p1.relativize(p2)
res6: java.nio.file.Path = ../../../../index.html

scala> p1.normalize.relativize(p2)
res7: java.nio.file.Path = ../index.html
I adapted the code to Linux environment, so "c:\\something" became "/something".

What's confusing me is why normalized and non-normalized versions produce different results.

Also, it seems to break the invariant:

Code: Select all

scala> p1.resolve(p1.relativize(p2)).normalize
res10: java.nio.file.Path = /index.html

scala> p1.resolve(p1.normalize.relativize(p2)).normalize
res11: java.nio.file.Path = /personal/index.html

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 30, 2016 7:16 pm
by admin
p1 and p1.normalize contain different path elements. So why do you think relativize should return the same value?

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 7:42 am
by ssszzz
Hello.
I still do not understand something...

Javadoc says
Relativization is the inverse of resolution. 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.
Lets check:

Code: Select all

    public static void main(String... strings) {
        Path p1 = Paths.get("c:\\personal\\.\\photos\\..\\readme.txt");
        Path p2 = Paths.get("c:\\personal\\index.html");
        System.out.println("p1=\t" + p1);
        System.out.println("p2=\t" + p2);

        Path p3 = p1.relativize(p2);
        System.out.println("p3=\t" + p3 + "\t/*this is a relative path, a result of p1.relativize(p2)*/");

        System.out.println("p1.resolve(p3)=\t" + p1.resolve(p3));
        System.out.println("(p1.resolve(p3)).normalize()=\t" + (p1.resolve(p3)).normalize());
    }
The output:

Code: Select all

p1=	c:\personal\.\photos\..\readme.txt
p2=	c:\personal\index.html
p3=	..\..\..\..\index.html	/*this is a relative path, a result of p1.relativize(p2)*/
p1.resolve(p3)=	c:\personal\.\photos\..\readme.txt\..\..\..\..\index.html
(p1.resolve(p3)).normalize()=	c:\index.html
So, p2 != p1.resolve(p3). Question N1: Why ?
Maybe it is because of
Where both paths have a root component then it is implementation dependent if a relative path can be constructed.
Both paths have root components, right? So, question N2: is the answer ('..\..\..\..\index.html') really correct to this puzzle?

Or maybe it is related to JDK-6925169 (but i could not find description of this bug)?

tested on build 1.8.0_131-b11

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 8:19 am
by admin
On a windows system, a path starting with c:\\ is a path with root component. But not so on a *nix system.
So if you use paths with c:\\ and try p.relativize(p.resolve(q)).equals(q) on windows, it may not print true. But on *nix, it will print true.

HTH,
Paul.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 10:34 am
by ssszzz
operation system is not mentioned in the question, although the paths look like windows paths.
So we have to think it does not matter where code is running.
So if you use paths with c:\\ and try p.relativize(p.resolve(q)).equals(q) on windows, it may not print true.

- of course and everywhere, since according javadoc for this expression to be fulfilled the path q should not have a root component and both paths should be normalized.
it is not our case.
We have two absolute paths and one of them is not normalized.
Moreover, we can just remove prefix "c:\\" from the example of code above to make them not absolute. What do we get? The same answer but without prefix "c:\\" (tested on windows)

So my questions remain in force.
1) why p.resolve(p.relativize(q)).normilize() != q.normilize() ? Note, it is not the same as expression above.
I think it is an equivalent of what javadoc says:

Code: Select all

Relativization is the inverse of {@link #resolve(Path) resolution}.
- it is the second line of method description.
Or I am not right and the expression and statement are not equivalent? Then how I can test this statement ('relativization is the inverse of resolution') ?
or maybe it is not true for two absolute windows-style paths where one of them has '..' inside (i.e. maybe it is mythical JDK-6925169)?

2) or maybe if it is not true since
Where both paths have a root component then it is implementation dependent if a relative path can be constructed
? If so, how we can calculate the true answer at all? It is unpredictable on windows.
What about linux? In the discussion above said that there is also problem here - instead '/personal/index.html' we get '/index.html'. I.e. almost the same answer,

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 11:23 am
by admin
Don't use absolute path on windows for p and q and p.relativize(p.resolve(q)).equals(q) will print true.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 11:47 am
by ssszzz
what about p.resolve(p.relativize(q)).equals(q)?
Observe that if you append this path to p1, you will get p2.
(this is from puzzle explanation)
so, p1.resolve(p3).equals(p2) should return true? for not absolute path? or for absolute also? or for windows? or everywhere?

By the way
Don't use absolute path on windows for p and q and p.relativize(p.resolve(q)).equals(q) will print true.
Lets check:

Code: Select all

    public static void main(String... strings) {
        String r = "\\"; // "c:\\"; // "";
        Path p1 = Paths.get(r + "personal\\.\\photos\\..\\readme.txt");
        Path p2 = Paths.get(r + "personal\\index.html");
        System.out.println("p1=\t" + p1 + "; absolute=" + p1.isAbsolute() + "; root=" + p1.getRoot());
        System.out.println("p2=\t" + p2 + "; absolute=" + p2.isAbsolute() + "; root=" + p2.getRoot());

        Path p3 = p1.relativize(p2);
        System.out.println("p3=\t" + p3 + "\t/*this is a relative path, a result of p1.relativize(p2)*/");

        System.out.println("p1.resolve(p3).equals(p2) = " + p1.resolve(p3).equals(p2)); // output: false

        System.out.println("p1.resolve(p1.relativize(p2)).equals(p2) = " + p1.resolve(p1.relativize(p2)).equals(p2)); // output: false
        System.out.println("p1.relativize(p1.resolve(p2)).equals(p2) = " + p1.relativize(p1.resolve(p2)).equals(p2));

        System.out.println("p1.resolve(p3)=\t" + p1.resolve(p3));
        System.out.println("(p1.resolve(p3)).normalize()=\t" + (p1.resolve(p3)).normalize());
    }
output:

Code: Select all

p1=	\personal\.\photos\..\readme.txt; absolute=false; root=\
p2=	\personal\index.html; absolute=false; root=\
p3=	..\..\..\..\index.html	/*this is a relative path, a result of p1.relativize(p2)*/
p1.resolve(p3).equals(p2) = false
p1.resolve(p1.relativize(p2)).equals(p2) = false
p1.relativize(p1.resolve(p2)).equals(p2) = false
p1.resolve(p3)=	\personal\.\photos\..\readme.txt\..\..\..\..\index.html
(p1.resolve(p3)).normalize()=	\index.html
So, no. it will not print true for two not absolute paths if they have roots. but if no roots - yes, p.relativize(p.resolve(q)).equals(q) == true.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 11:57 am
by admin
Sorry, I mistyped. I meant path with roots in my head but wrote absolute paths instead. Sorry about about that.
The following does print true:
Path p1 = Paths.get("personal\\.\\photos\\..\\readme.txt");
Path p2 = Paths.get("personal\\index.html");
System.out.println(p1.relativize(p1.resolve(p2)).equals(p2));

-Paul.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 12:04 pm
by ssszzz
how to append path p3 to p1 to get p2? I mean programmatically, not like in explanation

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 12:21 pm
by admin

Code: Select all

        Path p1 = Paths.get("personal\\.\\photos\\..\\readme.txt");
        System.out.println("p1=" + p1.normalize());
        Path p2 = Paths.get("personal\\index.html");
        System.out.println("p2=" + p2.normalize());
        Path p3 = p1.normalize().relativize(p2);
	System.out.println("p3="+p3);
	System.out.println("p="+p1.resolve(p3).normalize());
Output:

Code: Select all

p1=personal\readme.txt
p2=personal\index.html
p3=..\index.html
p=personal\index.html
So what is the issue?

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sat Jul 01, 2017 12:33 pm
by ssszzz
in the line Path p3 = p1.normalize().relativize(p2);
p1.normalize() = ''personal\\readme.txt"
and the answer is "p3=..\index.html".
It is not correct. The correct is "p3=..\..\..\..\index.html"

Code: Select all

        Path p1 = Paths.get("personal\\.\\photos\\..\\readme.txt");
        Path p2 = Paths.get("personal\\index.html");
        Path p3 = p1.relativize(p2);
        System.out.println("p3=" + p3); // output: p3=..\..\..\..\index.html
        System.out.println("p=" + p1.resolve(p3).normalize()); // output: p=..\..\index.html
and, it seems, the issue is in java
I do not know how much you can trust the following explanation, but people are talking about a bug in Path#relativize https://stackoverflow.com/questions/377 ... 2#37749932 (mysterious bug JDK-6925169)
The Path implementation does not handle . and .. components correctly in relativize, but treats them like any other path component.
So, in my opinion, there is either a bug, or poor documentation. And the question is about edge case, with not correct explanation of answer.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Mon Feb 19, 2018 9:09 am
by Ariskatsaris
In java 9 I tested the code exactly:

Code: Select all

Path p1 = Paths.get("c:\\personal\\.\\photos\\..\\readme.txt");
Path p2 = Paths.get("c:\\personal\\index.html");
Path p3 = p1.relativize(p2);
System.out.println(p3);
And it prints
..\index.html

namely answer (c) which is what I would have expected to.

I'm guessing that the implementation changed between Java 8 and Java 9. I think perhaps a note should be added to this effect, so that it doesn't confused people.

Where I'm concerned the Java 9 implementation is very clearly the correct and proper one, and the Java 7/Java 8 are horrible bugs. Consider for example the following snippet of code:

Code: Select all

        Path p1 = Paths.get("c:\\personal\\.\\photos\\");
        Path p2 = Paths.get("c:\\personal\\photos");
        Path p3 = p1.relativize(p2);
        System.out.println("Relative: " + p3);

        Path p4 = p1.resolve(p3);
        System.out.println("Resolved: " + p4);
        System.out.println("Normalized: " + p4.normalize());
In Java 9 it prints the reasonable:
Relative:
Resolved: c:\personal\.\photos
Normalized: c:\personal\photos

In Java 7 and Java 8 it prints the horrible and just plain wrong:
Relative: ..\..\photos
Resolved: c:\personal\.\photos\..\..\photos
Normalized: c:\photos

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Thu Apr 12, 2018 12:51 pm
by shamran99
Hi,

Can I understand the relativize() function's behavior like..
whatever the path elements('.' , '..' , 'file.txt' or 'dir') are included in the path object, the relativize considers it as a directory.
Therefore it relativize the path with '..'?

Regards,
Shamran.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Thu Apr 12, 2018 8:54 pm
by admin
Yes, that seems correct.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Fri Aug 03, 2018 9:11 am
by __JJ__
p1.relativize(p2) => how to get to p2 from p1.
It might be worth pointing out that relativize DOES NOT normalize before working out the result, and consequently
p1.normalize().relativize(p2) will potentially give you a completely different result to p1.relativize(p2):

Code: Select all

        Path p1 = Paths.get("c:\\personal\\.\\photos\\..\\readme.txt");
        Path p2 = Paths.get("c:\\personal\\index.html");
        Path p3 = p1.relativize(p2);
        System.out.println(p3); //..\..\..\..\index.html <== actual answer
        System.out.println(p1.normalize().relativize(p2)); //..\index.html <== what I thought would be the answer..

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Thu Aug 23, 2018 2:30 pm
by nowkarol
I noticed that (maybe it is file system dependent) having same thing on both sides doesn't result in adding /..
This seem obvious, but it couter intuitive that:

Code: Select all

Path p1 = Paths.get("/personal/.././readme.txt");
Path p2 = Paths.get("/personal/./../index.html");
have different result than

Code: Select all

Path p1 = Paths.get("/personal/.././readme.txt");
Path p2 = Paths.get("/personal/.././index.html");

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Tue Oct 23, 2018 7:11 pm
by Mark7777
All these questions and answers have my head spinning. Here's my question. First, the code:

Path p1 = Paths.get("c:\\personal\\.\\photos\\..\\readme.txt");
Path p2 = Paths.get("c:\\personal\\index.html");
Path p3 = p1.relativize(p2);

I learned in K & B that the objective is to get from readme.txt to index.html. Do that by counting upward the number of directories from readme.txt. Tell me if I'm wrong, but I'm assuming I stop at \personal\ because that is the directory both paths have in common, and I don't need to count back to the root. So I count up four directories," \\personal\\.\\photos\\..\\" including the single dot (.) which is not removed because we're not normalizing. That gives me ..\..\..\.., the fourth directory being \personal\. So I jump to the \personal\ of p2 and attach \index.html, and now I have ..\..\..\..\index.html. Right? Go up four directories, jump over to p2's \personal\ and attach index.html. And then I can double-check it using your technique.

Am I correct in assuming that in counting up the directory tree I don't need to go to the root c: which both paths have in common? I stop at the first directory they have in common, that being \personal\. And, am I correct in counting the first \\..\\ directory, and the \\.\\ (one dot current directory)?

Thanks in advance.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Tue Oct 23, 2018 9:27 pm
by admin
Yes, that is correct. You should try out more examples to confirm.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Wed Aug 07, 2019 10:31 am
by BinSlayer
While it's fine for OCP 8, this question is also present in OCP 11 Pt 2. That means the correct answer is the 3rd answer and not the 1st. Couldn't you guys update it in OCP 11?

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Wed Aug 07, 2019 11:09 am
by admin
You are right. We have gone through all questions involving relativize and have made sure they use the logic used by Java 11 in the OCP 11 Pt 2 question bank (version 1.12).

thank you for your feedback!

PS. We just sent you an email.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sun Aug 18, 2019 3:51 pm
by JoesJavaAccount
Hi,

I've just downloaded the Java 11 upgrade exam and came across this as well. Am I right in now assuming that the correct answer here should now be "..\\index.html" ? That's the answer I chose but it was marked incorrect, and still says the correct answer should be "..\..\..\..\index.html"
My version is v11.2.1584.

Thank

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sun Aug 18, 2019 10:55 pm
by admin
Apparently the change did not propagate to the upgrade question bank. I have verified that it has now been updated there as well in version 1.12.

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sun Sep 01, 2019 5:17 am
by marcioggs
I'm using Java 8 with Oracle's JDK and this is being printed:

Code: Select all

..\index.html

Code: Select all

>java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)

Code: Select all

>ver
Microsoft Windows [versão 10.0.17763.678]

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Sun Sep 01, 2019 11:32 pm
by admin
On Java 8 ( v.1.8.0.21) , it prints ..\..\..\..\index.html
On Java 11,(11.0.2), it prints, ..\index.html

Re: About Question enthuware.ocpjp.v8.2.1584 :

Posted: Thu Feb 20, 2020 3:50 am
by bvrulez
As from the explanation "if both paths have a root component" it is dependent of the implementation if a relative path can be constructed. So, this question is a bit out of scope but as I understand it might be on the exam, anyway. Also, after reading through the comments, I suppose some implementation on the base of Java 8 will deliver wrong results if compiled with Java 11 now. But probably, that's normal. Thanks for your work!