I am working in a java code that was designed to run on windows and contains a lot of references to files using windows style paths "System.getProperty("user.dir")\trash\blah". I am in charge to adapt it and deploy in linux. Is there an efficient way to convert all those paths(\) to unix style (/) like in "System.getProperty("user.dir")/trash/blah". Maybe, some configuration in java or linux to use \ as /.
My approach is to use the Path object to hold the path information, handle concatenate and relative path. Then, call Path's toString() to get the path String.
For converting the path separator, I preferred to use the apache common io library's FilenameUtils. It provides the three usefule functions:
String separatorsToSystem(String path);
String separatorsToUnix(String path);
String separatorsToWindows(String path)
Please look the code snippet, for relative path, toString, and separator changes:
private String getRelativePathString(String volume, Path path) {
Path volumePath = Paths.get(configuration.getPathForVolume(volume));
Path relativePath = volumePath.relativize(path);
return FilenameUtils.separatorsToUnix(relativePath.toString());
}
I reread your question and realize you likely don't need help writing paths. For what you're trying to do I am not able to find a solution. When I did this in a project recently I had to take time to convert all paths. Further, I made the assumption that working out of the "user.home" as a root directory was relatively sure to include write access for that user running my application. In any case, here are some path problems I addressed.
I rewrote the original Windows code like so:
String windowsPath = "C:\temp\directory"; //no permission or non-existing in osx or linux
String otherWindowsPath = System.getProperty("user.home") + "\Documents\AppFolder";
String multiPlatformPath = System.getProperty("user.home") + File.separator + "Documents" + File.separator + "AppFolder";
If you're going to be doing this in a lot of different places, perhaps write a utility class and override the toString() method to give you your unix path over and over again.
String otherWindowsPath = System.getProperty("user.home") + "\Documents\AppFolder";
otherWindowsPath.replace("\\", File.separator);
Write a script, replace all "\\" with a single forward slash, which Java will convert to the respected OS path.
Related
I am making an HTTP Server in Java so that (on start) it finds all files in a directory (and it's sub-directories) and adds them to the server. But when getting the path of a file and trying to give it to HttpServer.createContext(), it throws a java.lang.IllegalArgumentException: Illegal value for path or protocol. (with the string argument, say "\folder/index.html"). To get this value, I used
file.getParent().substring(24) + "/" + file.getName()
I used substring because I had to exclude the folder the web server is in. The illegal character is the backslash. I have tried extending File to change separator and separatorChar, but that only created 2 new variables. While using String.replace() didn't seem to have any effect. Is there a different method than File.getParent or File.getPath that I can use, or is there a way to use String.replace that I am not seeing?
EDIT:
String.replace() seems to be the best answer... But I am not completely sure how to use it.
EDIT 2: For some reason the backslash isn't showing up, so I changed it.
You have to use the java System.getProperty.
Notice that, in this context, "file.separator" is a key which we are
using to get this property from current system executing the java VM.
Insteady of using a slash (/), you should choose a platform agnostic file separator, as an example it should be:
String separator = System.getProperty("file.separator");
System.out.println(separator);
// unix / , windows \
Have a look at Paths.get(...)
Try Paths.get(".") // current working directory.
Or tell it, on which path it should start:
Use System.getProperty("user.dir"), for current loged in user, home directory.
String pathStr = "/";
Path homeDir = Paths.get(System.getProperty("user.dir"))
Getting from the user directory into the data directory: homeDir.get("data")
Path dataPath = Paths.get(System.getProperty("user.dir"));
File dataFile = dataPath.toFile();
Now use operations on dataFile, to check what files and directories there are, on that location of the file system.
I do not own a Windows copy, but would like to know the behavior and recommended usage in Java for representing a path such as \autoexec.bat under Windows?
Semantically, such a path would represent the file autoexec.bat on the root of any file system. Thus it would need to be resolved against a path representing a disk drive (such as C:\) before representing a file. In that sense, it is not absolute. However, it also does not have a root component, I suppose.
Can such path be created when running the JVM on Windows? If so, what would getRoot() and isAbsolute() return?
I tried the following code using Memory File System, but this throws InvalidPathException: “path must not start with separator at index 1: \truc”. Does this faithfully reflect the behavior under Windows, or is it a quirk of this specific library?
try (FileSystem fs = MemoryFileSystemBuilder.newWindows().build()) {
final Path truc = fs.getPath("\\truc");
LOGGER.info("Root: {}.", truc.getRoot());
LOGGER.info("Abs: {}.", truc.isAbsolute());
LOGGER.info("Abs: {}.", truc.toAbsolutePath());
}
Such paths are valid in the Windows terminal, or at least they were last time I used Windows (a long time ago). It would be handy to create such path in order to mark that the path is “absolute” (in the sense of starting with a backslash, thus not relative to a folder), but still leave the path without a driver letter specified. Then such a path can be (later) resolved to C:\autoexec.bat or D:\autoexec.bat or …
In Windows, \\ refers to the current drive which is C:\ in my case.
Not sure how the MemoryFileSystemBuilder works but the following code
File file = new File("\\test.txt");
final Path truc = file.toPath();
System.out.println("Root: " + truc.getRoot().toString());
System.out.println("Abs: " + truc.isAbsolute());
System.out.println("Abs: " + truc.toAbsolutePath().toString());
gives the below output
Root: \
Abs: false
Abs: C:\test.txt
Below is a path to my Windows directory. Normally the path should have \ instead of // but both seem to work.
String WinDir = "C://trash//blah//blah";
Same for a Linux path. The normal should have a / instead of //. The below and above snippet work fine and will grab the contents of the files specified.
String LinuxDir = "//foo//bar//blah"
So, both use strange declarations of file paths, but both seem to work fine. Elaboration please.
For example,
File file = new File(WinDir);`
file.mkdir();`
Normally, when specifying file paths on Windows, you would use backslashes. However, in Java, and many other places outside the Windows world, backslashes are the escape character, so you have to double them up. In Java, Windows paths often look like this: String WinDir = "C:\\trash\\blah\\blah";. Forward slashes, on the other hand, do not need to be doubled up and work on both Windows and Unix. There is no harm in having double forward slashes. They do nothing to the path and just take up space (// is equivalent to /./). It looks like someone just did a relpace of all backslashes into forward slashes. You can remove them. In Java, there is a field called File.separator (a String) and File.separatorChar (a char), that provide you with the correct separator (/ or \), depending on your platform. It may be better to use that in some cases: String WinDir = "C:" + File.separator + "trash" + File.separator + "blah" + File.separator + "blah";
With java.nio.path, you even better get an independent OS path without any concern about path delimiter.
public class PathsGetMethod {
public static void main(String[] args) {
Path path = Paths.get("C:\\Users\\conta\\OneDrive\\", "desktop", "data");
System.out.println(path);
//C:\Users\conta\OneDrive\desktop\data
}
}
I am having a little issue trying to figure out the best solution to the my path problems. I am running a java test that I want to get two things.
The absolute location of the project
The absolute location to the current class file that is running
I want to proper / or \ being on the OS version so the folder structure stays intact. I am currently using this but it is not exactly what I am looking for
final String parentDir = System.getProperty("user.dir");
final String path = "src/test/java/" + method.getDeclaringClass()
.getCanonicalName().replaceAll("\\.", "/") + ".java";
Any help would be appreciated. Thanks
Update: I am trying to get the url of the precompiled code as I need access to the comments in the code. This may change some of your guys answers
Update 2: Ok I got it to work.
final String path = new File(getClass().getResource("/").getFile())
.getParent().split("target")[0] + "src/test/java/" + method
.getDeclaringClass().getCanonicalName()
.replaceAll("\\.", "/") + ".java";
Thanks Guys
Given that you are calling this from MyClass you should call
File directory = (new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath())).getParentFile();
I had the same question once. In addition to Jatin's answer I had to add an toURI() to get the correct path on all platforms (Windows, etc.) and post 1.5 JVMs.
If say you are running from jar file:
new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent()+"/"
returns the folder containing the jar file.
Remove the .getParent() above to get path to the exact class file
I have a String that provides an absolute path to a file (including the file name). I want to get just the file's name. What is the easiest way to do this?
It needs to be as general as possible as I cannot know in advance what the URL will be. I can't simply create a URL object and use getFile() - all though that would have been ideal if it was possible - as it's not necessarily an http:// prefix it could be c:/ or something similar.
new File(fileName).getName();
or
int idx = fileName.replaceAll("\\\\", "/").lastIndexOf("/");
return idx >= 0 ? fileName.substring(idx + 1) : fileName;
Notice that the first solution is system dependent. It only takes the system's path separator character into account. So if your code runs on a Unix system and receives a Windows path, it won't work. This is the case when processing file uploads being sent by Internet Explorer.
new File(absolutePath).getName();
Apache Commons IO provides the FilenameUtils class which gives you a pretty rich set of utility functions for easily obtaining the various components of filenames, although The java.io.File class provides the basics.
From Apache Commons IO FileNameUtils
String fileName = FilenameUtils.getName(stringNameWithPath);
Here are 2 ways(both are OS independent.)
Using Paths : Since 1.7
Path p = Paths.get(<Absolute Path of Linux/Windows system>);
String fileName = p.getFileName().toString();
String directory = p.getParent().toString();
Using FilenameUtils in Apache Commons IO :
String name1 = FilenameUtils.getName("/ab/cd/xyz.txt");
String name2 = FilenameUtils.getName("c:\\ab\\cd\\xyz.txt");