Java Cross Platform File Operations - java

I developed a software in netbeans + Ubuntu and then converted the runnable .jar file of netbeans to .exe file using a converter software.
I used:
File f = new File("./dir/fileName");
which works fine in Ubuntu but it gives an error in Windows, because the directory pattern of both OSs are different.

Absolute paths should not be hardcoded. They should be read e.g. from a config file or user input.
Then you can use the NIO.2 File API to create your file paths: Paths.get(...) (java.io.File is a legacy API).
In your case it could be:
Path filePath = Paths.get("dir", "fileName");

I used: File f = new File("./dir/fileName") which works fine in Ubuntu but it gives error in Windows, bcz the directory pattern of both os are different.
It is presumably failing because that file doesn't exist at that path. Note that it is a relative path, so the problem could have been that the the path could not be resolved from the current directory ... because the current directory was not what the application was expecting.
In fact, it is perfectly fine to use forward slashes in pathnames in Java on Window. That's because at the OS level, Windows accepts both / and \ as path separators. (It doesn't work in the other direction though. UNIX, Linux and MacOS do not accept backslash as a pathname separator.)
However Puce's advice is mostly sound:
It is inadvisable to hard-code paths into your application. Put them into a config file.
Use the NIO2 Path and Paths APIs in preference to File. If you need to assemble paths from their component parts, these APIs offer clean ways to do it while hiding the details of path separators. The APIs are also more consistent than File, and give better diagnostics.
But: if you do need to get the pathname separator, File.separator is an acceptable way to get it. Calling FileSystem.getSeparator() may be better, but you will only see a difference if your application is using different FileSystem objects for different file systems with different separators.

You can use File.separator as you can see in api docs:
https://docs.oracle.com/javase/8/docs/api/java/io/File.html

Related

Filename include slash punctuation and gives Exception in thread "main" java.io.FileNotFoundException: foo/boo/en_en.json (No such file or directory)

I am trying to create a new file as a boo/en_en.json to foo folder, but IntelliJ Idea thinks that boo is a directory and en_en.json is a file. How should I fix that problem?
My code is:
val target = new PrintWriter(new File(s"foo/$name-$locale.json"))
And name includes slash punctuation.
Operating system is MacOs Sierra.
Its not intellij that blocking it, you cant put slash in your file names underlying api is blocking it.
You shouldn't be able to create a file with a / in it's name on OSX through the java api. You can manually do this in the finder, but it's silently replacing the / with a : in the file name it actually saves to disk. If you want it to appear in finder as a /, then save it with a :. Any programs that access the file will have to refer to it with the :
This is due to differences between legacy mac file system paths and unix filesystem paths.
However, it's a terrible idea to ever have a / in a filename, since it is incredibly confusing.

Best way to process command line file path argument in Java

I'd like to pass a file path argument to my application in a relative form, e.g ~/test.conf or ../test.conf, but i can't get a proper full file path, though i've tried it with old java.io and new java.nio Files/Paths. Is there a general way to get a resolved file path without large amount of code? It would be fine for the solution to work only in unix envs like OsX or Debian.
Update
With a provided argument like ~/test.conf
in case of getAbsolutePath it returns a path with a prefixed current folder - /Users/currentUser/Projects/Personal/TestProject/~/text.conf. Canonical path returns the same.
The hard bit here is dealing with POSIX home directories, and sure you deal with ~otheruser/dir/test.conf too (if you want to do it properly).
Luckily that's covered in How to handle ~ in file paths.
TL;DR - use something like:
path.replace("~/", System.getProperty("user.home") + "/");
Once you've done that, and as others have commented, you can just use standard java.io methods (including getCanonicalPath()).

Platform Independent File Storage Java

I was making a Java game that stores options and the LWJGL jars in the standard application data storage directory (I think that's C:\Users\user\AppData\roaming\application on Windows, ~/.application on Linux, and ~/Library/Preferences on Mac). Currently I just use System.getProperty(os.name) and have an if-else to select the right file path (which uses system.getProperty(user.home) and appends the correct file path to it). However, this might not work on some weird OSs because the if-else won't find Windows, Mac, or Linux in the OS name, and this also seems to be a very bad way to do this in general (also the if-else assumes the OS is Linux if it isn't Windows or Mac). I tried decompiling Minecraft, which stores the app data and the LWJGL jars in the correct path, but the code is obfuscated. Is there any better way for me to do this, or should I stick with an if-else on os.name?
Java Preferences API was created specifically for such purpose.
For configuration preferences, there is the Java Preferences API.
For other files, I have not found a solution to this. The best solution, at present, is probably to dispatch on the OS type with a fallback based on the user.home property.
On Linux/Unix (not Mac), you might want to honor the XDG Base Directory specification.
Shouldn't a path like this work everywhere, i.e. without the if-else-if:
String userHome = System.getProperty("user.home");
if (!userHome.endsWith("/")) {
userHome += "/";
}
String targetPath = userHome + ".myapp/settings.properties";

How to open file with default application in SWT?

I have for example .pdf file (path to that file). How to open this file in default application (probably Acrobat Reader) from SWT application (for example on Button click) ?
You should be able to use:
Program.launch(file);
to open the file (using the default application or creator). From the javadoc:
Launches the operating system executable associated with the file or URL (http:// or https://). If the file is an executable then the executable is launched. Note that a Display must already exist to guarantee that this method returns an appropriate result.
Note that there are some peculiarities in Program.launch() (or at least there were, though these may have been fixed in more recent versions of the runtime.) I don't really remember the specifics of the bugs, but we do some checks to work around some issues:
If you're on a Unix platform, and you're specifying an absolute path, there may be trouble opening that file. We prefix absolute paths with /. - so that /tmp/foo would be translated to /./tmp/foo - although I don't really remember the specifics of this bug any more than that.
On Windows, if you're trying to open a UNC path - for example \\server\bar - you need to wrap the string in double-quotes. For example: Program.open("\"\\server\bar\"");
Try Desktop.open:
Desktop.getDesktop().open(file);
Maybe this can help to find a decision: we ran into PermGen space trouble upon call Desktop.open() - which is in AWTpackage - out of our SWT application.
So I would prefer Program.launch() over Desktop.open() in a SWT-environment.

File paths in Java (Linux)

I have created a Java application that loads some configurations from a file conf.properties which is placed in src/ folder.
When I run this application on Windows, it works perfectly. However when I try to run it on Linux, it throws this error:
java.io.FileNotFoundException: src/conf.properties (No such file or directory)
If you've packaged your application to a jar file, which in turn contains the properties file, you should use the method below. This is the standard way when distributing Java-programs.
URL pUrl = this.getClass().getResource("/path/in/jar/to/file.properties");
Properties p = new Properties();
p.load(pUrl.openStream());
The / in the path points to the root directory in the jar file.
Instead of
String PROP_FILENAME="src/conf.properties";
use
String PROP_FILENAME="src" + File.separator + "conf.properties";
Check the API for more detail: http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html
I would also check what your current working directory is if your path to that file is relative. You just need to make a File test = new File("."); and then print that files canonical path name.
If you are referencing any other locations like user.dir or something to that effect by using System.getProperty(), you'll want to at least verify that the directory you are using as the relative root is where you think it is.
Also, as Myles noted, check the slashes used as file path separators. Although you can always use the "/" and it works.
And if you are referencing the path absolutely, you'll have trouble going between one OS and another if you do something silly like hard-code the locations.
What you want to do is check out System.getProperties() and look for file.separator. The static File.pathSeprator will also get you there.
This will allow you to build a path that is native for whatever system you're running on.
(If indeed that is the problem. Sometimes I like to get the current directory just to make sure the directory I think I'm running in is the directory I'm really running in.)
Check your permissions. If you (or rather, the user that the Java process is running under) doesn't have appropriate permissions to read the file, for example, you would get this error message.
This is a typical Windows -> Linux migration problem. What does ls -l src/conf.properties show when run from a prompt?
Additionally, check capitalisation. Windows isn't case-sensitive, so if the file was actually called e.g. CONF.properties it would still be found, whereas the two would be considered different files on Linux.
You should check the working directory of your application. Perhaps it is not the one you assume and that's why 'src' directory is not present.
An easy check for this is to try the absolute path (only for debugging!).
I would check your slashes, windows often uses '\' vs linux's '/' for file paths.
EDIT: Since your path looks fine, maybe file permissions or executing path of the app is different?
check your slashes and colons
in my case i set my PS1 to following value
PS1='\n[\e[1;32m]$SYSNAME(\u)#[\e[1;33m]\w [\e[1;36m](\d \T) [!]\e[0m]\n\$ '
i am trying to read from the env .such as system.getenv
Java was throwing exception
java.lang.IllegalArgumentException: Malformed \uxxxx encoding
Try the double slash, after doing things in JBoss I often had to refactor my code to use the double slashes

Categories

Resources