Accessing external files within Java applications under Windows and Linux Operating Systems - java

Please I am facing the following issue:
Throughout my Java program, i am accessing some files which it seems they are being accessed in a different way under windows compared to Linux. For example, if i wanted to access the following file within the same folder as the project i would write the following:
Under Linux: File Operations_File = new File("Data/Operations.txt");
Under Windows: File Operations_File = new File("Data\\Operations.txt");
I will be needing a standard methodology that works under all operating systems (or at least those two). As coding two versions of my code is not elegant at all.
My Two operating system that I am operating on are: Linux Mint 9 and Windows XP. I used NetBeans 6.9.1 throughout all the project.
Your help is greatly appreciated!

File.separator is exactly for this.
File f = new File("Data" + File.separator + "Operations.txt");
Don't get confused with File.pathSeparator, that is used to separate paths from each other. For example:
/usr/local/lib:/usr/lib:/var/lib
In the above example, : is the path separator (windows uses ; for path separators).

You can also create a File representing the directory and another File representing something in that directory like this:
File dataDir = new File("Data");
File operationsFile = new File(dataDir, "Operations.txt");
You could also skip the File for the directory and just do this as well:
File operationsFile = new File("Data", "Operations.txt");
Under Windows, printing out operationsFile gives Data\Operations.txt as expected.

Related

File being created at user.home instead of relative path in Ubuntu

I am seeing different behavior between Windows, Ubuntu, and Manjaro when creating files. Windows and Manjaro correctly are creating files in the relative path of the jar. However, Ubuntu seems to be creating the files at the user.home location instead.
File file = new File("file.ext");
The files are being created a couple different ways...
// 1 Normal
try (FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {}
// 2 ImageIO
BufferedImage bufferedImage = ImageIO.read(new URL(imageUrl));
imgFile.createNewFile();
ImageIO.write(bufferedImage, "jpg", imgFile);
// 3 Log4J
<RollingFile name="RollingFile" fileName="./log/output-${date:yyyyMMdd}.log" filePattern="./log/output-%d{yyyyMMdd}.log">
// 4 Sqlite
Connection sqlite = DriverManager.getConnection(String.format("jdbc:sqlite:%s", dbFileName));
All of these files are ending up in the user home in Ubuntu. I've tried the path name plain file.ext and ./file.ext but neither works.
Additional system details:
Ubuntu Desktop 20.04
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-8u265-bo1-6ubuntu2~20.04-bo1)
OpenIDK 64-Bit Server VM (build 25.265-bo1, mixed mode)
EDIT:
It seems that this happens when running the jar from double click after making it executable chmod +x myproject.jar. It seems that running the jar via terminal java -jar myproject.jar the files appear in the relative path beside the jar.
Something about the executable/double click is causing them to appear in the user.home
Maybe you are on the wrong current directory. May I ask if you did open the terminal of Ubuntu and run the build commands?
new File( "file" ) and new File( "./file" ) both will create the file with the name "file" in the current working directory. What this is depends on various factors, not only on the operating system.
You may call your program (indirectly) through a startup script that sets the current working directory, some operating systems (more specifically, the respective shell) set it either to the program location or to the user's home or use the current directory for it (or think about something else …).
That means that the location for . inside your program depends completely from the execution environment. This in turn means that you should never make any assumptions what this location should be, not even that you can write to it (you may not even be able to read from it).
So yes, your observation is true, but that is expected and well known. And it is no feature (or bug) of Java or any particular JVM, nor is it really an operating system specific, although it may look like.

Converting linux path to windows path

I'm looking for a way to map every linux directory absolute path to a windows path.
for example: whenever my app is accessing /var/log , it will actually access c:/base-folder/var/log .
My Java app was written in a way that only linux machines can run it. One of the reasons for this constraint is the filesystem paths. I cannot change all paths to a relative paths.
The solution can be in OS level (e.g running from command line cd /var/log will open c:/base-folder/var/log ) or Java level (new File("/var/log") equals to new File("c:/base-folder/var/log") ).
Writing javaagent that changes File and Path classes is not possible, as my app is already running with different javaagent.
Using the built in ubuntu on windows won't work either, because the IDE is on windows.

Shell script java program not writing files correctly

I have a java program that syncs the content of two directories. The program takes the two directories as arguments.
I created a shell script to run the program on Linux. When the program firsts runs it creates a .sync file in each directory, this work perfectly on windows but is causing me some issues on linux. I'm very new to linux so unsure what is really going on.
My program uses the following piece of code to create the .sync file...
FileWriter fileDir1 = new FileWriter(dir1 + "\\.sync");
fileDir1.write(obj.toJSONString());
fileDir1.flush();
fileDir1.close();
When I run the program on linux the files are being created in the same directory as the two directories are located instead of inside the two directories. The resulting files look like this..
dir1\.sync and dir2\.sync
Any help would be great.
Use a forward slash / instead of an escaped backslash \\, it works both on Windows and Linux.
FileWriter fileDir1 = new FileWriter(dir1 + "/.sync");

Java user.dir is not always correct

Im making a basic .bat file that runs the application. This is to get auto startup feature.
However for some reason System.getProperty("user.dir") does not always get the correct path to the program.
Basically i am saving this to the .bat file:
protected final String fileSeparator=System.getProperty("file.separator");
out.println("#echo off");
out.println("start " + System.getProperty("user.dir") + fileSeparator +"App.jar");
out.println("exit");
On Windows server it returns the correct path but on Vista it does not.
Any ideas how i could get this to work on all versions of Windows?
You can do this by providing user.dir when you start your Java program like this
java somepackage.Main -Duser.dir=C:/Users/myUser
user.dir = User working directory
[from documentation ]
It is difficult to take decision based on value of this variable. Depending on the program starting the "java", it could have different values. For example, a bat file could have different working directory from invoked from different command-windows.
You could use %~dp0 to get location of the batch script and then put other paths relative to this.
Another option is to use tools like launch4j, which allows an easy way to control program directory : How to get the path to the executable when using launch4j?

Store paths in property files

I have Java app which runs on Linux and Windows and app depends of path of some program ( I need to read two paths in my app, one if I on windows and second if I on Linux, I read which OS in my code ). How to achive this with property file ?
What about simply adding both properties?
org.example.linux.path=...
org.example.windows.path=...
And read the property you need
String path = props.getProperty("org.example." + getOS() + ".path");
EDIT: btw, you can get an idea of different system properties and their respective values from this question
You can read O.S. by
System.getProperty("os.name");
and then conditionally read properties file
you can use
System.getProperty("os.name")
You have a property file for each OS and decide which one to load depending on the operating system you run on. For example linux.properties will contain the Linux paths while windows.properties will contain the windows paths.
just a thought not necessarily correct. Can we try having a property with key as
DS = "\" for one operating system and
DS1 = "/" for another operating system and we select it on the basis of whether i am on windows or mozilla.
and we save paths as
path = "c:".DS."dir1".DS."dir2"

Categories