Reputation: 129287
I have developed a number of classes which manipulate files in Java. I am working on a Linux box, and have been blissfully typing new File("path/to/some/file");
. When it came time to commit I realised some of the other developers on the project are using Windows. I would now like to call a method which can take in a String of the form "/path/to/some/file"
and, depending on the OS, return a correctly separated path.
For example:
"path/to/some/file"
becomes "path\\to\\some\\file"
on Windows.
On Linux it just returns the given String.
I realise it wouldn't take long to knock up a regular expression that could do this, but I'm not looking to reinvent the wheel, and would prefer a properly tested solution. It would be nice if it was built in to the JDK, but if it's part of some small F/OSS library that's fine too.
So is there a Java utility which will convert a String path to use the correct File separator char?
Upvotes: 32
Views: 77037
Reputation: 272297
Apache Commons IO
comes to the rescue (again). The Commons IO
method FilenameUtils.separatorsToSystem(String path)
will do what you want.
Needless to say, Apache Commons IO
will do a lot more besides and is worth looking at.
Upvotes: 52
Reputation: 1920
Path
implements Iterable<Path>
which iterates the name components of the path.
E.g. Path.of(path/to/some/file)
iterator()
results in [path, to, some, file]
.
Combine with String.join
and you can change the separator:
Path path = Path.of("path/to/some/file");
List<String> nameElements = StreamSupport.stream(path.spliterator(), false).map(Path::toString).toList();
String newSeparator = "\\";
String newPath = String.join(newSeparator, nameElements);
Not the most elegant with the Iterable
to Stream
conversion, though. It'd be nice if String.join
accepted Iterable<Object>
and invoked toString
for you.
Then it could be written like:
Path path = Path.of("path/to/some/file");
String newSeparator = "\\";
String newPath = String.join(newSeparator, path);
Upvotes: 1
Reputation: 2103
In Scala, the below code helps us to generate a windows-compliant
path name from a linux
compliant path.
def osAwareFilename(path: String) : String = {
val pathArr = path.split("/")
if (System.getProperty("os.name").contains("Windows")) {
pathArr.mkString("\\")
}
else path
}
Upvotes: 0
Reputation: 33092
A "/path/to/some/file"
actually works under Windows Vista and XP.
new java.io.File("/path/to/some/file").getAbsoluteFile()
> C:\path\to\some\file
But it is still not portable as Windows has multiple roots. So the root directory has to be selected in some way. There should be no problem with relative paths.
Edit:
Apache commons io does not help with envs other than unix & windows. Apache io source code:
public static String separatorsToSystem(String path) {
if (path == null) {
return null;
}
if (isSystemWindows()) {
return separatorsToWindows(path);
} else {
return separatorsToUnix(path);
}
}
Upvotes: 19
Reputation: 409
I think there is this hole in Java Paths.
String rootStorePath = Paths.get("c:/projects/mystuff/").toString();
works if you are running it on a system that has the file system you need to use. As pointed out, it used the current OS file system.
I need to work with paths between windows and linux, say to copy a file from one to another. While using "/" every works I guess if you are using all Java commands, but I need to make an sftp call so using / or file.separator
etc... does not help me. I cannot use Path()
because it converts mine to the default file system I am running on "now".
What Java needs is:
on windows system:
Path posixPath = Paths.get("/home/mystuff", FileSystem.Posix );
stays /home/mystuff/ and does not get converted to \\home\\mystuff
on linux system:
String winPath = Paths.get("c:\home\mystuff", FileSystem.Windows).toString();
stays c:\home\mystuff
and does not get converted to /c:/home/mystuff
similar to working with character sets:
URLEncoder.encode( "whatever here", "UTF-8" ).getBytes();
P.S. I also do not want to load a whole apache io jar file to do something simple either. In this case they do not have what I propose anyways.
Upvotes: 0
Reputation: 13649
I create this function to check if a String contain a \
character then convert them to /
public static String toUrlPath(String path) {
return path.indexOf('\\') < 0 ? path : path.replace('\\', '/');
}
public static String toUrlPath(Path path) {
return toUrlPath(path.toString());
}
Upvotes: 2
Reputation: 2556
This is what Apache commons-io does, unrolled into a couple of lines of code:
String separatorsToSystem(String res) {
if (res==null) return null;
if (File.separatorChar=='\\') {
// From Windows to Linux/Mac
return res.replace('/', File.separatorChar);
} else {
// From Linux/Mac to Windows
return res.replace('\\', File.separatorChar);
}
}
So if you want to avoid the extra dependency, just use that.
Upvotes: 10
Reputation: 83
String fileName = Paths.get(fileName).toString();
Works perfectly with Windows at least even with mixed paths, for example
c:\users\username/myproject\myfiles/myfolder
becomes
c:\users\username\myproject\myfiles\myfolder
Sorry haven't check what Linux would make of the above but there again Linux file structure is different so you wouldn't search for such a directory
Upvotes: 1
Reputation: 4106
For anyone trying to do this 7 years later, the apache commons separatorsToSystem method has been moved to the FilenameUtils class:
FilenameUtils.separatorsToSystem(String path)
Upvotes: 2
Reputation: 55
With the new Java 7 they have included a class called Paths this allows you to do exactly what you want (see http://docs.oracle.com/javase/tutorial/essential/io/pathOps.html)
here is an example:
String rootStorePath = Paths.get("c:/projects/mystuff/").toString();
Upvotes: 3
Reputation: 9
Shouldn't it be enough to say:
"path"+File.Seperator+"to"+File.Seperator+"some"+File.Seperator+"file"
Upvotes: 0
Reputation: 21
Do you have the option of using
System.getProperty("file.separator")
to build the string that represents the path?
Upvotes: 2