Since Path.resolve does not accept an array of strings, it is possible pass a relative path containing multiple path components, e.g. "foo/bar/baz".
My question is
if the forward slash in such a relative path will work as intended across platforms?
I have seen some answers on here that allege Java treats forward slashes as a "universal separator", but not citations to support them.
/ should be a valid path separator on all major platforms of today. See for instance File.separator vs Slash in Paths (maybe it's even a dup?)
If you're the pedantic type you can use FileSystem.getSeparator.
Note that you can also do
root.resolve(Paths.get("foo", "bar", "baz"));
No. The typical / in Path objects is called a name separator. It is defined in the FileSystem object from which the Path was created.
You can retrieve it with FileSystem#getSeparator().
Returns the name separator, represented as a string.
The name separator is used to separate names in a path string. An
implementation may support multiple name separators in which case this
method returns an implementation specific default name separator. This
separator is used when creating path strings by invoking the
toString() method.
In the case of the default provider, this method returns the same
separator as java.io.File.separator.
You can retrieve a Path's FileSystem with Path#getFileSystem().
As far as I know, all typical file systems will use / as a separator, but you could write your own FileSystem implementation which doesn't.
You can do first FileSystem.getPath("foo", "bar", "baz") to get Path and instead of sending String to Path.resolve() you can use overloaded one which accepts Path.
Related
I want to get String separated by forward-slash / from java.nio.file.Path.
However, toString uses backward-slash \ as a separator on Windows machines.
Example: https://www.geeksforgeeks.org/path-tostring-method-in-java-with-examples/
Is there good solutions?
Candidates that I have are following. But I don't think they are good ideas.
replace File.pathSeparator by /
join Path.iterator() by /
Sharing context, I want to use org.eclipse.jgit.ignore.IgnoreNode.
checkIgnored only has poor interface that accepts String rather than Path and it seems to works with only paths separated by /.
I am using the Java URL constructor "URL(URL context, String spec)" found here but the constructed URL is not what I expect - it is leaving out a path segment provided in the context parameter.
As an example, this code
new URL(new URL("http://asdf.com/z"), "a/b/c");
produces a URL with value
http://asdf.com/a/b/c
So it has left out of "z" path segment.
I have two questions:
What is the meaning of "context" the first parameter here in the java doc? I could not find mention of it in the URL specification nor did I really find it in java doc.
Is leaving out the "z" expected behavior?
Thanks!
What is the meaning of "context" the first parameter here in the java doc?
It's like the "base URL" of the spec parameter. If context is https://example.com, and spec is /foo, the constructor would create https://example.com/foo. It's similar to (but not exactly the same as, as we'll see later) asking "I am currently on https://example.com, and I want to go to /foo, what would my final URL be?"
Is leaving out the "z" expected behavior?
Yes. If you follow through the rules of resolving a relative URL against an base URL in RFC 2396 with regards to this case, you will reach this step:
(6) If this step is reached, then we are resolving a relative-path
reference. The relative path needs to be merged with the base
URI's path. Although there are many ways to do this, we will
describe a simple method using a separate string buffer.
(a) All but the last segment of the base URI's path component is
copied to the buffer. In other words, any characters after the
last (right-most) slash character, if any, are excluded.
(b) The reference's path component is appended to the buffer
string.
The "last segment" here, refers to z, and that is not added to the buffer. Right after that, the path a/b/c "is appended to the buffer". Steps (c) onwards deals with removing . and .., which is irrelevant here.
Note that RFC 2386 doesn't say you MUST implement the algorithm in this way, but that whatever your implementation is, your output must match the output of that algorithm:
The above algorithm is intended to provide an example by which the
output of implementations can be tested -- implementation of the
algorithm itself is not required.
So yeah, this is expected. To keep the /z, you should add another / after the z:
new URL(new URL("http://asdf.com/z/"), "a/b/c")
This way the "last segment" becomes the empty string.
You can treat the context like the current directory in file system.
With context "http://asdf.com/z", the current directory is "http://asdf.com/", and use "a/b/c" as the spec will result a full path "http://asdf.com/a/b/c".
What is the deal with Java's bizarre file protocol handling?
I mean on windows UNC path's get turned into 5 slashes, and I get why that happens, but on linux an absolute path gets turned into file:/local/path/to/file
Shouldn't that have three slashes?
I'm assuming the authors of Java aren't incompetent, so is there an explanation for why that's acceptable?
Let’s start with the documentation of the URI class:
A hierarchical URI is subject to further parsing according to the syntax
[scheme:][//authority][path][?query][#fragment]
As you can see, the authority is optional. This is supported by the URI specification, section 3:
The scheme and path components are required, though the path may be empty (no characters). When authority is present, the path must either be empty or begin with a slash ("/") character. When authority is not present, the path cannot begin with two slash characters ("//").
A file: URI can have an authority separator, //, with an effectively empty authority after it, but it serves no purpose, so there is no harm in omitting it. It’s still a fully compliant URI.
I am trying to escape forward slash in String which can be used in path using Java.
For example: String:: "Test/World"
Now I want to use above string path.At the same time I have to make sure that "Test/World" will come as it is in path. Sorry if its duplicate but I couldn't find any satisfactory solution for this.
My purpose is to use above string to create nodes in Zookeeper.
Example:
If I use following string to create node in Zokkeeper then I should get "Test/World" as a single node not separate. Zookeeper accepts "/" as path separator which in some cases I dont require.
/zookeeper/HellowWorld/Test/World
Thanks
You should know about File.separator ... This is safer than \ or / because Linux and Windows use different file separators. Using File.separator will make your program run regardless of the platform it is being run on, after all, that is the point of the JVM. -- forward slash will work, however, File.separator will make you end users more confident that it will.
And you don't need to escape "/ ... you should also see the answer to this question
String fileP = "Test" + File.separator + "World";
In order to escape a character in Java use "\"
for example:
String strPath = "directory\\file.txt".
I believe you do not need to escape forward slashes such as: "/"
Let me rephrase your question. You are trying to create a node in zookeeper and it should be /zookeeper/HelloWorld/NodeName. But the last part "NodeName" is actually "Test/World", and you are looking for ways to escape "/" so the node name can be "Test/World".
I don't think it would work escaping the char, unless you tried with unicode.
Try \u002F which is the equivalent for /.
We are trying to solve exactly the same problem (using filesystem path as node name in zookeeper) a we haven't found a way how to have '/' in node name.
Solution would be either to replace '/' with some character, that cannot appear in your node name. For paths that would be '/' or '\0', which wont help us in this case.
Other possibility is to replace '/' with string of characters allowed in node name, e.g. "Test/World" -> "Test%#World", "Test%World" -> "Test%%World" and add escaping/de-escaping to saving and loading.
If there is any more straightforward way, I'd love to hear it.
I don't know anything about Zookeeper. But it looks to me as though you're trying to keep a list of strings like "zookeeper", "HellowWorld", "Test/World", that you then want to use either to create Zookeeper nodes or to create a pathname in a file system. (I'm assuming that if you're working with a file system, you're going to have a subdirectory Test and a file or subdirectory World in the Test subdirectory. If you're actually trying to create a single file or directory named Test/World, give up. Both Linux and Windows will fight with you.)
If that's the case, then don't try to represent the "path" as a simple String that you pass around in your program. Instead, represent it as a String[] or ArrayList<String>, and then convert it to a filesystem path name only when you need a filesystem path name. Or, better, define your own class with a getFilesystemPath method. Converting your list of node names to a pathname String too early, and then trying to reconstruct the list from the String later, is a poor approach because you throw away data that you need later (in particular, you're throwing away information about which / characters are separators and which ones are part of node names).
EDIT: If you also need a single path name for Zookeeper, as you mentioned in another comment, I can't help you since I don't know Zookeeper and haven't found anything in a quick look at the docs. If there is a way to escape the slash for Zookeeper, then I still recommend defining your own class, with a getFilesystemPath method and a getZookeeperPath method, since the two methods will probably return different Strings in certain cases. The class would internally keep the names as an array or ArrayList.
I have to create a file based on a string provided to me.
For this example, let's say the file name is "My file w/ stuff.txt".
When Java creates the file using
File file = new File("My file w/ stuff.txt")
Even though the default windows separator is '\', it assumes that the '/' slash is a file separator. So a future call to file.getName() would return " stuff.txt". This causes problems for my program.
Is there any way to prevent this behaviour?
According to this Wikipedia page, the Windows APIs treat / as equivalent to \. Even if you somehow managed to embed a / in a pathname component in (for example) a File object, the chances are that Windows at some point will treat it as a path separator.
So your options are:
Let Windows treat the / as it would normally; i.e. let it treat the character as a pathname separator. (Users should know this. It is a "computer literacy" thing ... for Windows users.)
As above, but with a warning to the user about the /.
Check for / AND \ characters, and reject both saying that a filename (i.e. a pathname component) cannot contain pathname separators.
Use some encoding scheme to encode reserved characters before attempting to create the files. You must also then apply the (reverse) decoding scheme at all points where you need to show the user their "file name with slashes".
Note: if the user can see the actual file paths (e.g. via a command shell) you can't hide the encoding / decoding from them. Arguably, that is worse than the "problem" you were trying to solve in the first place.
There is no escaping scheme that the Windows OS will accept for this purpose. You would need to use something like % encoding; e.g. replace / with %2F. Basically you need to "hide" the slash character from Windows by replacing it with other characters in the OS-level pathname!
The best option depends on details of your application; e.g. whether you can report problems to the person who entered the bogus filename.
If a string is being provided to you (from an external source), it doesn't sound like you can prevent that string from containing certain characters. If you have some sort of GUI to create the string, then you can always restrict it there. Otherwise, whatever method is creating your file should check for a slash and either return an error or handle it as you see fit.
Since neither forward nor backward slashes are allowed in windows file names, they should be cleaned out of the Strings used to name files.
Well, how could you stop it being a folder separator? It is a folder separator. If you could just decide for yourself what was and what wasn't a folder separator, then the whole system would come crashing down.