How to get the path of running java program [duplicate] - java

This question already has answers here:
Find where java class is loaded from
(12 answers)
Closed 9 years ago.
Is there a way to get the path of main class of the running java program.
structure is
D:/
|---Project
|------bin
|------src
I want to get the path as D:\Project\bin\.
I tried System.getProperty("java.class.path"); but the problem is, if I run like
java -classpath D:\Project\bin;D:\Project\src\ Main
Output
Getting : D:\Project\bin;D:\Project\src\
Want : D:\Project\bin
Is there any way to do this?
===== EDIT =====
Got the solution here
Solution 1 (By Jon Skeet)
package foo;
public class Test
{
public static void main(String[] args)
{
ClassLoader loader = Test.class.getClassLoader();
System.out.println(loader.getResource("foo/Test.class"));
}
}
This printed out:
file:/C:/Users/Jon/Test/foo/Test.class
Solution 2 (By Erickson)
URL main = Main.class.getResource("Main.class");
if (!"file".equalsIgnoreCase(main.getProtocol()))
throw new IllegalStateException("Main class is not stored in a file.");
File path = new File(main.getPath());
Note that most class files are assembled into JAR files so this won't work in every case (hence the IllegalStateException). However, you can locate the JAR that contains the class with this technique, and you can get the content of the class file by substituting a call to getResourceAsStream() in place of getResource(), and that will work whether the class is on the file system or in a JAR.

Use
System.getProperty("java.class.path")
see http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html
You can also split it into it's elements easily
String classpath = System.getProperty("java.class.path");
String[] classpathEntries = classpath.split(File.pathSeparator);

Try this code:
final File f = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
replace 'MyClass' with your class containing the main method.
Alternatively you can also use
System.getProperty("java.class.path")
Above mentioned System property provides
Path used to find directories and JAR archives containing class files.
Elements of the class path are separated by a platform-specific
character specified in the path.separator property.

You actually do not want to get the path to your main class. According to your example you want to get the current working directory, i.e. directory where your program started. In this case you can just say new File(".").getAbsolutePath()

ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url: urls){
System.out.println(url.getFile());
}

Related

java.lang.NullPointerException when using getClass().getResource() to load an image [duplicate]

I am trying to load an image to use as an icon in my application. The appropriate method according to this tutorial is:
protected ImageIcon createImageIcon(String path, String description)
{
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
So, I placed the location of the file, and passed it as a parameter to this function. This didn't work, i.e. imgURL was null. When I tried creating the ImageIcon by passing in the path explicitly:
ImageIcon icon = new ImageIcon(path,"My Icon Image");
It worked great! So the application can pick up the image from an explicitly defined path, but didn't pick up the image using getResources(). In both cases, the value of the path variable is the same. Why wouldn't it work? How are resources found by the class loader?
Thanks.
getClass().getResource(path) loads resources from the classpath, not from a filesystem path.
You can request a path in this format:
/package/path/to/the/resource.ext
Even the bytes for creating the classes in memory are found this way:
my.Class -> /my/Class.class
and getResource will give you a URL which can be used to retrieve an InputStream.
But... I'd recommend using directly getClass().getResourceAsStream(...) with the same argument, because it returns directly the InputStream and don't have to worry about creating a (probably complex) URL object that has to know how to create the InputStream.
In short: try using getResourceAsStream and some constructor of ImageIcon that uses an InputStream as an argument.
Classloaders
Be careful if your app has many classloaders. If you have a simple standalone application (no servers or complex things) you shouldn't worry. I don't think it's the case provided ImageIcon was capable of finding it.
Edit: classpath
getResource is—as mattb says—for loading resources from the classpath (from your .jar or classpath directory). If you are bundling an app it's nice to have altogether, so you could include the icon file inside the jar of your app and obtain it this way.
As a noobie I was confused by this until I realized that the so called "path" is the path relative to the MyClass.class file in the file system and not the MyClass.java file. My IDE copies the resources (like xx.jpg, xx.xml) to a directory local to the MyClass.class. For example, inside a pkg directory called "target/classes/pkg. The class-file location may be different for different IDE's and depending on how the build is structured for your application. You should first explore the file system and find the location of the MyClass.class file and the copied location of the associated resource you are seeking to extract. Then determine the path relative to the MyClass.class file and write that as a string value with "dots" and "slashes".
For example, here is how I make an app1.fxml file available to my javafx application where the relevant "MyClass.class" is implicitly "Main.class". The Main.java file is where this line of resource-calling code is contained. In my specific case the resources are copied to a location at the same level as the enclosing package folder. That is: /target/classes/pkg/Main.class and /target/classes/app1.fxml. So paraphrasing...the relative reference "../app1.fxml" is "start from Main.class, go up one directory level, now you can see the resource".
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("../app1.fxml"));
Note that in this relative-path string "../app1.fxml", the first two dots reference the directory enclosing Main.class and the single "." indicates a file extension to follow. After these details become second nature, you will forget why it was confusing.
getResource by example:
package szb.testGetResource;
public class TestGetResource {
private void testIt() {
System.out.println("test1: "+TestGetResource.class.getResource("test.css"));
System.out.println("test2: "+getClass().getResource("test.css"));
}
public static void main(String[] args) {
new TestGetResource().testIt();
}
}
output:
test1: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
test2: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
getResourceAsStream() look inside of your resource folder. So the fil shold be placed inside of the defined resource-folder
i.e if the file reside in /src/main/resources/properties --> then the path should be /properties/yourFilename.
getClass.getResourceAsStream(/properties/yourFilename)

ClassNotFoundException while using Class.forName()

I am trying to use Java reflection to read class files and output its contents. Here is my Reflect.java file code that throws the error:
String className = classNames.get(classNum).replace(".class", "");
String packageAndClassName = packageName + "." + className;
System.out.println(packageAndClassName);
try{
Class<?> c = Class.forName(packageAndClassName);
My command to read a package's contents looks like this
java -classpath . reflect.Reflect package /u/username/Desktop/Experiment/others/package/
Here, arg[0]= package and arg[1]=/u/username/Desktop/Experiment/others/package/
My classpath looks like so:
/u/username/Desktop/Experiment/reflect/:/u/username/Desktop/Experiment/others/package/
"others" contains the package. I have no idea what I am doing wrong. I have looked up a lot of answers and they involve typing in the whole name of the Reflect class, which I am doing in my command. Any ideas as to what I'm missing?
You should pay attention to the classpath parameter. I'm guessing the class you are trying to load is not in the path so you need to add the package directory there.
The other option is to use the UrlClassLoader

Loading a custom class from arbitrary location

I am having some issues with Class Loading in Java. Inside my project I am trying to dynamically load a class from anywhere. However, I am currently failing at loading a hard-coded one and am still clueless after 6 hours of googling and stack-overflow checking.
I am suspecting that there is an issue with the package name of the class I am loading.
My goal is to load the Class LoadAClass.java in the project/resources/dynamicFolderNonInClassPath/loadThis directory. Since I am setting my URLClassLoader to the folder above, its package has been set to
package loadThis;
public class LoadAClass{
static{
System.out.println("I am loaded");
}
(...)
}
However I keep getting a class not found exception.
File file = new File("C:/Users/Robert/Documents/workspace/project/resources/dynamicFolderNonInClassPath/");
if (!file.exists()) System.out.println("typo!"); //debug print
URL url = file.toURI().toURL();
URLClassLoader loader = new URLClassLoader(new URL[]{url});
String classToBeLoaded = "loadThis.LoadAClass";
Class classy = loader.loadClass(classToBeLoaded);
System.out.println(classy.getCanonicalName()); //debug print
I have tried different combinations, like setting the URLClassLoader to the file directly or giving the full /resources/dynamicFolderNonInClassPath/loadThis as URL but how so far no success.
Someone in christmasy mood and seeing the problem? There seems to be some misunderstanding on my part regarding this functionality and I'd like to see it fixed.
you are missing a forward slash '/'
File file = new File("C:/Users/Robert/Documents/workspace/project/resources/dynamicFolderNonInClassPath");
if (!file.exists()) System.out.println("typo!"); //debug print
URL url = new URL("C:/Users/Robert/Documents/workspace/project/resources/dynamicFolderNonInClassPath/");
URLClassLoader loader = new URLClassLoader(new URL[]{url});
String classToBeLoaded = "loadThis.LoadAClass";
Class classy = loader.loadClass(classToBeLoaded);
System.out.println(classy.getCanonicalName()); //debug print
See the third line
A .java file isn't a class file. Have you compiled it? You would need a LoadAClass.class file in a "loadThis" directory with your class loader pointing at the directory that contains "loadThis".

How can I get relative path of the folders in my android project?

How can I get the relative path of the folders in my project using code?
I've created a new folder in my project and I want its relative path so no matter where the app is, the path will be correct.
I'm trying to do it in my class which extends android.app.Activity.
Perhaps something similar to "get file path from asset".
Make use of the classpath.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource("path/to/folder");
File file = new File(url.toURI());
// ...
Are you looking for the root folder of the application? Then I would use
String path = getClass().getClassLoader().getResource(".").getPath();
to actually "find out where I am".
File relativeFile = new File(getClass().getResource("/icons/forIcon.png").toURI());
myJFrame.setIconImage(tk.getImage(relativeFile.getAbsolutePath()));
With this I found my project path:
new File("").getAbsolutePath();
this return "c:\Projects\SampleProject"
You can check this sample code to understand how you can access the relative path using the java sample code
import java.io.File;
public class MainClass {
public static void main(String[] args) {
File relative = new File("html/javafaq/index.html");
System.out.println("relative: ");
System.out.println(relative.getName());
System.out.println(relative.getPath());
}
}
Here getPath will display the relative path of the file.
In Android, application-level meta data is accessed through the Context reference, which an activity is a descendant of.
For example, you can get the source directory via the getApplicationInfo().sourceDir property.
There are methods for other folders as well (assets directory, data dir, database dir, etc.).
Generally we want to add images, txt, doc and etc files inside our Java project and specific folder such as /images.
I found in search that in JAVA, we can get path from Root to folder which we specify as,
String myStorageFolder= "/images"; // this is folder name in where I want to store files.
String getImageFolderPath= request.getServletContext().getRealPath(myStorageFolder);
Here, request is object of HttpServletRequest. It will get the whole path from Root to /images folder. You will get output like,
C:\Users\STARK\Workspaces\MyEclipse.metadata.me_tcat7\webapps\JavaProject\images
With System.getProperty("user.dir") you get the "Base of non-absolute paths" look at
Java Library Description

Changing the current working directory in Java?

How can I change the current working directory from within a Java program? Everything I've been able to find about the issue claims that you simply can't do it, but I can't believe that that's really the case.
I have a piece of code that opens a file using a hard-coded relative file path from the directory it's normally started in, and I just want to be able to use that code from within a different Java program without having to start it from within a particular directory. It seems like you should just be able to call System.setProperty( "user.dir", "/path/to/dir" ), but as far as I can figure out, calling that line just silently fails and does nothing.
I would understand if Java didn't allow you to do this, if it weren't for the fact that it allows you to get the current working directory, and even allows you to open files using relative file paths....
There is no reliable way to do this in pure Java. Setting the user.dir property via System.setProperty() or java -Duser.dir=... does seem to affect subsequent creations of Files, but not e.g. FileOutputStreams.
The File(String parent, String child) constructor can help if you build up your directory path separately from your file path, allowing easier swapping.
An alternative is to set up a script to run Java from a different directory, or use JNI native code as suggested below.
The relevant OpenJDK bug was closed in 2008 as "will not fix".
If you run your legacy program with ProcessBuilder, you will be able to specify its working directory.
There is a way to do this using the system property "user.dir". The key part to understand is that getAbsoluteFile() must be called (as shown below) or else relative paths will be resolved against the default "user.dir" value.
import java.io.*;
public class FileUtils
{
public static boolean setCurrentDirectory(String directory_name)
{
boolean result = false; // Boolean indicating whether directory was set
File directory; // Desired current working directory
directory = new File(directory_name).getAbsoluteFile();
if (directory.exists() || directory.mkdirs())
{
result = (System.setProperty("user.dir", directory.getAbsolutePath()) != null);
}
return result;
}
public static PrintWriter openOutputFile(String file_name)
{
PrintWriter output = null; // File to open for writing
try
{
output = new PrintWriter(new File(file_name).getAbsoluteFile());
}
catch (Exception exception) {}
return output;
}
public static void main(String[] args) throws Exception
{
FileUtils.openOutputFile("DefaultDirectoryFile.txt");
FileUtils.setCurrentDirectory("NewCurrentDirectory");
FileUtils.openOutputFile("CurrentDirectoryFile.txt");
}
}
It is possible to change the PWD, using JNA/JNI to make calls to libc. The JRuby guys have a handy java library for making POSIX calls called jnr-posix. Here's the maven info
As mentioned you can't change the CWD of the JVM but if you were to launch another process using Runtime.exec() you can use the overloaded method that lets you specify the working directory. This is not really for running your Java program in another directory but for many cases when one needs to launch another program like a Perl script for example, you can specify the working directory of that script while leaving the working dir of the JVM unchanged.
See Runtime.exec javadocs
Specifically,
public Process exec(String[] cmdarray,String[] envp, File dir) throws IOException
where dir is the working directory to run the subprocess in
If I understand correctly, a Java program starts with a copy of the current environment variables. Any changes via System.setProperty(String, String) are modifying the copy, not the original environment variables. Not that this provides a thorough reason as to why Sun chose this behavior, but perhaps it sheds a little light...
The working directory is a operating system feature (set when the process starts).
Why don't you just pass your own System property (-Dsomeprop=/my/path) and use that in your code as the parent of your File:
File f = new File ( System.getProperty("someprop"), myFilename)
The smarter/easier thing to do here is to just change your code so that instead of opening the file assuming that it exists in the current working directory (I assume you are doing something like new File("blah.txt"), just build the path to the file yourself.
Let the user pass in the base directory, read it from a config file, fall back to user.dir if the other properties can't be found, etc. But it's a whole lot easier to improve the logic in your program than it is to change how environment variables work.
I have tried to invoke
String oldDir = System.setProperty("user.dir", currdir.getAbsolutePath());
It seems to work. But
File myFile = new File("localpath.ext");
InputStream openit = new FileInputStream(myFile);
throws a FileNotFoundException though
myFile.getAbsolutePath()
shows the correct path.
I have read this. I think the problem is:
Java knows the current directory with the new setting.
But the file handling is done by the operation system. It does not know the new set current directory, unfortunately.
The solution may be:
File myFile = new File(System.getPropety("user.dir"), "localpath.ext");
It creates a file Object as absolute one with the current directory which is known by the JVM. But that code should be existing in a used class, it needs changing of reused codes.
~~~~JcHartmut
You can use
new File("relative/path").getAbsoluteFile()
after
System.setProperty("user.dir", "/some/directory")
System.setProperty("user.dir", "C:/OtherProject");
File file = new File("data/data.csv").getAbsoluteFile();
System.out.println(file.getPath());
Will print
C:\OtherProject\data\data.csv
You can change the process's actual working directory using JNI or JNA.
With JNI, you can use native functions to set the directory. The POSIX method is chdir(). On Windows, you can use SetCurrentDirectory().
With JNA, you can wrap the native functions in Java binders.
For Windows:
private static interface MyKernel32 extends Library {
public MyKernel32 INSTANCE = (MyKernel32) Native.loadLibrary("Kernel32", MyKernel32.class);
/** BOOL SetCurrentDirectory( LPCTSTR lpPathName ); */
int SetCurrentDirectoryW(char[] pathName);
}
For POSIX systems:
private interface MyCLibrary extends Library {
MyCLibrary INSTANCE = (MyCLibrary) Native.loadLibrary("c", MyCLibrary.class);
/** int chdir(const char *path); */
int chdir( String path );
}
The other possible answer to this question may depend on the reason you are opening the file. Is this a property file or a file that has some configuration related to your application?
If this is the case you may consider trying to load the file through the classpath loader, this way you can load any file Java has access to.
If you run your commands in a shell you can write something like "java -cp" and add any directories you want separated by ":" if java doesnt find something in one directory it will go try and find them in the other directories, that is what I do.
Use FileSystemView
private FileSystemView fileSystemView;
fileSystemView = FileSystemView.getFileSystemView();
currentDirectory = new File(".");
//listing currentDirectory
File[] filesAndDirs = fileSystemView.getFiles(currentDirectory, false);
fileList = new ArrayList<File>();
dirList = new ArrayList<File>();
for (File file : filesAndDirs) {
if (file.isDirectory())
dirList.add(file);
else
fileList.add(file);
}
Collections.sort(dirList);
if (!fileSystemView.isFileSystemRoot(currentDirectory))
dirList.add(0, new File(".."));
Collections.sort(fileList);
//change
currentDirectory = fileSystemView.getParentDirectory(currentDirectory);

Categories

Resources