This is a 100% win console application.
So here's the problem.
I want to load the file music.xm that I want to place inside the jar.
The problem come up when I try to call the file through a relative path. The start directory it's not the Java project one, but my Windows User Folder.
If I call
File music = new File("\\music.xm");
javax.sound.sampled.UnsupportedAudioFileException: /C:/Users/XXXX/Desktop/./music/music.xm
If I call
File music = new File(".\\music.xm");
I get
javax.sound.sampled.UnsupportedAudioFileException: /C:/music.xm
If its in your jar, you can use
getclassLoader().getResourceAsStream("music.xm")
You can use this inputStream however you like. But remember, the path should be relative to classpath root of the classloader.
In addition, if you are sure "music.xm" exists as an independent file on filesystem in a fixed relative location to your .class files you can also use :
getclassLoader().getResource("music.xm")
You can look on SO and here for documentation.
Related
Image DescriptionTrying to access a test.txt file that is in the same location as my HelloController.java file but for some reason, it is showing that the file does not exist. I've tried moving the file around but it does not work.
Using the absolute path works, but this is a shared project so it will be ran on other computers. Any suggestions would be much appreciated.
Your best bet is to add it to the class path and reading it as a class path resource.
The relative path root is your "working directory". Which means if you try to access "." you will start at your working directory. This directory is only set once for your application and is normally the folder which was opened when you started it.
When working with IDEs (like in your case) the working directory will be the root folder of your project (So the folder in which the pom.xml and src folders are located.
If you want to access the file via the normal file API you are currently using, just put the file in that diretory and it should work (given you share it with the other people in the same location).
If you need the file to be inside your generated output jar-file, you will need to use the File as a resource (See duffymo's answer), as the file does not exist by itself on the file system, but as a file inside your jar-file.
If you want to know your current working directory, you can create a File refrence to "." and expand it to an absolute path (Which will replace refrences like "." and ".." and generate a file path from your root) and then write it to the console. This would look something like this:
// Get refrence to the current working directory
File workingDirectoryReference = new File(".");
// Convert it to an absolute path string
String absolutePath = workingDirectoryReference.getAbsolutePath();
// Output to console
System.out.println(absolutePath );
When I call method
System.out.print(new File("").getAbsolutePath())
from main I get the project workspace
C:\Users\darkr\Desktop\NuovoWorkSpace\ProjectName.
When it gets called by our save() method, which serializes what we need, suddenly the absolute path given from
new File("").getAbsolutePath()
becomes System32 (for me) and Desktop directory for my colleagues.
We're using gitHub to share our changes but this makes it almost impossible.
The code you have new File("").getAbsolutePath() is commonly used to determine the current directory from where you launched your application's main(String[]) method. So it looks like you are running from C:\Windows\System32 not on desktop folder.
The easiest way to fix your issue is to edit your application shortcut (see .lnk file and set "Start in" folder), or cd to be in an appropriate writable directory before running your application, or change your application to use file chooser to pick the target location for saves.
Alternatively pick sensible output paths for writing to instead of "", some good candidates are:
// Local user profile
File folder = new File(System.getenv("LOCALAPPDATA"), "myfolder");
// Roaming user profile
File folder = new File(System.getenv("APPDATA"), "myfolder");
// Temp folder:
File folder = new File(System.getProperty("java.io.tmpdir"), "myfolder")
Some sites suggest one of the following lines to locate Desktop, but this is unreliable because it will not work if the folder has been moved or run on some non-English installations:
File maybeDesktop = new File(System.getProperty("user.home"), "Desktop");
Path maybeDesktop = Path.of(System.getProperty("user.home"), "Desktop");
If you want to read the exact location of user Desktop from Java, you need to use JNI/JNA/Panama call to Windows API functions SHGetFolderPath or SHGetKnownFolderPath.
I'm trying to create a basic Java program that allows the user create files and folders.
I want all this to happen in a folder inside my project (image attached) so I've got some doubts...
This would be my proyect tree
Is the folder "Test" correctly placed? if not how do i access to it? As you see, it's inside com.company, should I move it to src?
When I try to check if exists, it says false.
This is my code:
public class Main {
Scanner input = new Scanner(System.in);
public static void main(String[] args) {
Main main = new Main();
main.init();
}
public void init(){
File f = new File("Test"); //Here i've tried "com"+File.separator+"company"+File.separator+"Test"
System.out.println(f.exists()); //output is false here
}
}
f.getParent() says null.
But when I try: System.out.println(f.getAbsolutePath()); it shows correctly the whole path.
The point of using relative path is because i'd like this code to work on ANY computer.
Thanks in advice, hope someone could help me a bit.
If you use relative pathnames in Java, they will be resolved relative to the running application's working directory. So you need to know what the working directory is going to be.
When you are launching an application in an IDE, the working directory depends on the IDE and the launcher configs. But it is typically the file system directory that corresponds to the top of the project.
Another thing to note is that the src folder you see is special. The entries in it are typically not files and directories. The are typically Java packages and classes. So in the file system, "src" > "com.company" > "Main" is actually represented as a file with the path "src/com/company/Main.java".
This means that it is kind of wrong to put arbitrary folders and files into the "src" folder. It will work ... but it is conceptually wrong. Data files don't belong in the source tree, and certainly not data files written by your application. (And when you start using a source control system, you will find that writing data files into your source tree is going to give you a headache. I won't go into details ... but I am pretty sure that you would regret it.)
The other thing that is conceptually wrong about what you are doing is that Java programs are normally written to be free standing things. The user of your program should not need to download and install Intellij or some other IDE and load your project into it. They will want to just run it from a JAR file. In that world, the project directory and the "src" folder won't exist, and hardwiring relative paths like "src/Test" will be problematic.
So lets ignore that for now and look at what your code is currently doing
Is the folder "Test" correctly placed? if not how do i access to it? As you see, it's inside com.company, should I move it to src?
According to the image, the Test folder (actually package) >>is<< in the src Folder.
When I try to check if exists, it says false.
Your code is using the wrong path. With the "Test" folder places where you have it (according to the picture!), the relative path should be "src/Test", not "Test" or "com/company/Test".
Note that Windows accepts either "/" or "\" will work as a file separator, even though "\" is what is used conventionally.
f.getParent() says null.
That is correct. The relative path "Test" does not have a parent part. It is a simple file / directory name.
Think of it this way. Until a File with a relative path is resolved, it is not determined what directory it is relative to.
But when I try: System.out.println(f.getAbsolutePath()); it shows correctly the whole path.
Again, correct.
When you call f.getAbsolutePath() on a relative File, the runtime system prepends the path of the application's working directory, and then gives you the result.
The point of using relative path is because I'd like this code to work on ANY computer.
That relative path will NOT work on ANY computer. You are using a path that is within your project's src tree, and your project typically won't exist on an end-user's computer. (See above.)
So what should you do?
There is no single correct answer.
You could put the file / directory into the user's current / working directory.
You could put the file / directory into the user's home directory, or a hidden subdirectory in the home directory. (This is a common approach on Linux.)
You could make the pathname for the directory a command line argument
You could get the pathname from an environment variable
You could get the pathname from an application specific config file.
The best answer will depend on the context.
According to your picture the path is wrong, you should check inside the src directory:
File f = new File("src/Test");
System.out.println(f.exists());
My program has to use certain files that reside in another directory. Right now I am using absolute path to specify the location of the files. But I know that the relative position of these files will remain the same compared to where my program is residing. How I can use relative path in Java to specify the location of these files?
For example my program is residing in
/home/username/project/src/com/xyz/
..and the target files are in..
/home/username/project/secure/
For example my program is residing in /home/username/project/src/com/xyz/
and the target files are in /home/username/project/secure/
Knowing the place where your program's source code resides does not help. What you need to know is the current directory of the program when it is executed. That could be literally anything. Even if you are launching the application from (for example) Eclipse, the application launcher allows you to specify the "current directory" for the child process in the Run configuration.
Your current path.
currentPath= /home/username/project/src/com/xyz/;
Relative path to "/home/username/project/secure/" folder is
relativePath= ../../../secure;
In Java you can use getParentFile() to traverse up the tree.
File currentDir = new File(".");
File parentDir = currentDir.getParentFile();
This will be safe as you are not using system dependent file separator (../)
Currently, in my eclipse project, I have a file that I write to. However, I have exported my project to a JAR file and writing to that directory no longer works. I know I need to treat this file as a classpath resource, but how do I do this with a BufferedWriter?
You shouldn't have to treat it as a classpath resource to write to a file. You would only have to do that if the file was in your JAR file, but you don't want to write to a file contained within your JAR file do you?
You should still be able to create and write to a file but it will probably be relative to the working directory - the directory you execute your JAR file from (unless you use an absolute path). In eclipse, configure the working directory from within the run configuration dialog.
You're probably working in Linux. Because, in Linux, when you start your application from a JAR, the working directory is set to your home folder (/home/yourname/). When you start it from Eclipse, the working directory is set to the project folder.
To make sure you really know the files you are using are located in the project folder, or the folder where your JAR is in, you can use this piece of code to know where the JAR is located, then use the File(File parent, String name) constructor to create your files:
// Find out where the JAR is:
String path = YourClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
path = path.substring(0, path.lastIndexOf('/')+1);
// Create the project-folder-file:
File root = new File(path);
And, from now on, you can create all your File's like this:
File myFile = new File(root, "config.xml");
Of course, root has to be in your scope.
Such resources (when altered) are best stored in a sub-directory of user.home. It is a reproducible path that the user should have write access to. You might use the package name of the main class as a basis for the sub-directory. E.G.
our.com.Main -> ${user.home}/our/com/