In Ruby I frequently use File.dirname(__FILE__) to open configuration files and such. For those that don't know Ruby, this will give the location on the file system of the file it's called from. This allows me to package libraries with data and config files and open those files with relative paths.
What's the Java equivalent of this? If there is a data file I want to package with a jar how would I open the data file from Java code that is also in the jar?
The equivalent API in Java is getResourceAsStream. This will open a stream to a file stored in the JAR relative to the class on which it is invoked.
There are variants, such as getResource, which returns a URL, or methods on ClassLoader that use an absolute path inside the JAR file.
Please see Java Applications and the "Current Directory":
In Java, you use File objects to
construct a relative view of the file
system. Two of the constructors for
the File object take a 'parent'
argument that specifies a parent path
that is prefixed to the path of the
file itself to create the full
abstract path to the file. What you do
is, create a File object with the path
that represents your current directory
and then create all your file objects
using that File object as the parent.
Voila, a current directory.
Also I would recommend Reading and Writing a Properties File:
// Read properties file.
Properties properties = new Properties();
try {
properties.load(new FileInputStream("filename.properties"));
} catch (IOException e) {
}
// Write properties file.
try {
properties.store(new FileOutputStream("filename.properties"), null);
} catch (IOException e) {
}
if you just specify the file name, the JVM will look for that file in the same directory your application was started (not necessarily the same directory your application is located).
I voted for #andrew, but I'd like to point out that in Java, the directory the file itself is pretty meaningless except for a few highly reflective (and most likely wrong) purposes.
It will be in a directory based on a package structure, and could be located in a jar or pretty much anywhere.
Java's a little less ad-hock, allowing for less shortcuts, but usually improving consistency and reliability at deployment time.
Related
I am loading my properties file using the class loader as follows.
Properties prop = new Properties();
prop.load(MyClass.class.getResourseAsStream("/Property.properties"));
Now, using this method I am able to read the properties file. I want to write some data to the property file. I don't know the path of the property file. How do I store the data to the property file then ?
Update
I tried the following, but it doesn't give me the correct path:
File propFile = new File("Property.properties");
System.out.println(propFile.getAbsolutePath());
I don't think you can in a generic way that would always work, because your properties file could be bundled inside a jar, etc. You can get the URL via getResource(String) and then do something with that URL, for example if it's a file URL, you could get the file name there.
URL u=MyClass.class.getResource("/Property.properties");
if ("file".equals(u.getProtocol()){
File f=new File(u.toURI());
}
But that wouldn't work in all cases.
I would write the modified value to a file in a well known location, and use the bundled Properties as the default value, that are overriden by the values in the file.
There are two parts to your question.
First, the reading part. You said: "I am loading my properties file ..." using the code you provided. This code treats the file as a "resource" and loads it using the class loader. The class loader mechanism in the Java Runtime comes into picture here. Roughly speaking, this mechanism searches for it in your application's current classpath and makes the input stream associated with first matching resource available to your code. It may be fine in your case, however, you should realize that if there are multiple properties files by the same name in different parts of your classpath (e.g. different JAR files having the same config file), then you may not know which file is being read. The only way to ensure that you are reading the right file from the classpath is to ensure that you have that config file in a unique place in your application's classpath.
This seems to work for you. Reading from a file is easier, than, say writing to a file.
In the second part, you want to write to a file. It's important to note that you should know the exact whereabouts of the file you are writing to. If you rather unknowingly convert it to an output stream, then you might end up trying to write to a stream that you are not allowed to write to. So, here, you should try to find the location (path) of the actual, physical file, for example, on a computer's hard drive. That path is something you should know before you write and run this program. Remember that a file always exists in a folder or a directory.
Your attempt:
File propFile = new File("Property.properties");
System.out.println(propFile.getAbsolutePath());
to find the location or path of the file you want to write to fails because when you do new File("Property.properties");, Java tries to refer to a file (does not do anything yet with the operating system) that resides in the Java Runtime's current working directory. This refers to the location given by System.getProperty("user.dir"). So, your propFile refers to a (hypothetical) file in that folder and the call to getAbsolutePath() prints its path. This is not the file that you want because you are trying to write to a file whose path you don't know. So, you should find the path of the file and then use a BufferedWriter backed by a FileWriter or BufferedOutputStream backed by a FileOutputStream to write to this file. Make sure that the file you want to write to exists and you have permission to write to it.
Essentially get the resource as an OutputStream, then pass it to the store() method of your Properties object.
Details here:
http://www.drdobbs.com/jvm/readwrite-properties-files-in-java/231000005
I'm developing a Dynamic Web Project in Eclipse. I created a .properties file for store database details (Username, Password etc.). I added it by right clicking on the project and New -> File . I used the Java util package Properties class. But it does not working. I can not retrieve any property from the file. Here is the code I used,
Properties prop = new Properties();
try {
prop.load(new FileInputStream("database.properties"));
String db = prop.getProperty("database");
String userName = prop.getProperty("dbuser");
String password = prop.getProperty("dbpassword");
} catch (IOException ex) {
ex.printStackTrace();
}
Is there something wrong or Is there any particular place where I should put properties file.
What you did is correct, ie right clicking the project and new--file.You have to Put your properties where you start your jvm from. Please look into the attached image. The properties file is marked in red. Look if your properties file is also located something like this.
Also add this in your code to find out where to put your file:
System.out.println(new File(".").getAbsolutePath());
For more details please follow this link- FileNotFoundException when using java properties file
Normally, you make sure the properties file is in the project runtime classpath (e.g. WEB-INF/classes) and then load it using either the System classloader or the property file handler's classloader, i.e. (Freehand typing from memory -- NOT COMPILED)
try{
Properties p = new Properties();
InputStream in = MyPropertyHandler.getClass()
.getClassLoader()
.getResourceAsStream("com/package/props/database.properties");
p.load(in);
catch(IOException e){
e.printStackTrace(System.err);
}
I'm betting you aren't pointing at the correct location. Make sure you're properties file is in the correct place. Using that code, I believe it is looking for ${CURRENT_WORKING_DIR}/database.properties, which is the case of a web app in eclipse is WEB-INF/classes (i think).
You should instead be using the more portable java.util.Properties#load(InputStream) with the result of javax.servlet.ServletContext#getResourceAsStream(String).
Try to give absolute path or relative path to the proprty file, also check this propery file path has been add to source folders or not, if not it will not be copied to your classes folder. (Right cclick on project , check java build path under source tab.
You should have .properties file in same package as class that is using it.
Or better, read properties file with getResourceAsStream method (otherwise you can have some problem later when you'll have file in .war archive).
InputStream inputStream =
getClass().getClassLoader().getResourceAsStream("database.properties");
Anyone plz let us know what to do when we have some configuration file which is basically xml.I want to for example give the path to save the image(for my java program) in a folder from some config file (xml in my case).In that case where should the config file be kept.Rt now every thing is converted to jar file when i create a java standalone package.But i want to give some setting from xml file.What to do in that case.How is it possible.This article only provides to create a single jar file for java project but talks nothing about the configuration settings that u can provide from some external source.
Regards
Sagar
I'm not sure I fully understand your question, but if it is where to put the XML file with configuration information, you can place your xml file in the same directory as your jar file, and then pass the XML file name and path into the Jar on the command line when calling the Jar. If you're running it in Windows, this is often done using a shortcut. Then you can get the full path string for the Jar from the main method's String[] arg array that accepts the command parameters.
Sagar,
The fact your java program is a standalone package (.jar file) has no bearing on where your configuration file is stored. Your java package is a program and that program can read any file from the file system that it so desires; it does not have to be part of the code inside the IDE i.e. you don't have to write it when you write the program. What you do need is some way, when you start the program, to find and read said configuration file.
Depending on how you expect the program to be configured, you might put that file in a number of locations. For example, /etc/yourimageprogram/config.xml or c:\program files\yourimageprogram\config.xml or perhaps c:\users\Sagar\Application Settings\yourimageprogram\config.xml. Which you choose of those options really depends on what the use case is and that I can't help with.
However, there are some main points to reading any file:
Does it exist?
Are we allowed to open it for reading?
Are we allowed to open it for writing? Might want to know if we want to update the config?
In Java, typically, you would test this with:
File configfile = new File("C:\test.xml");
if ( configfile.exists() && configfile.canRead() )
{
// read the file
}
else
{
// decide what to do if no config exists.
// might be first run of app.
}
The next stage is to parse the file. There are a number of parsers available for XML including sax and org.w3c.dom. What you need to do is to use these to extract the information you require and store that in a class. Probably a singleton class as you're unlikely to have multiple configuration instances per instance of the program.
I suggest you read about XML Parsers and File Handling under Java. Also look at the File object. See all your options for file io in java. These should give you some indication of how to proceed.
I'm trying to have my application load a resource (binary file) transparently:
If the file exists under the current directory, open it.
If not, try looking in the current JAR file if applicable.
If not, try looking in other JAR files. (This is optional and I don't mind explicitly specifying which JAR files.)
So far I know of File which opens a local file and ClassLoader which has getResource* for JAR contents.
Is there a class which combines the two? If not, how should I go about writing it myself? Should I write a ClassLoader which also checks the local filesystem? Using File? (I'm very unfamiliar with Java and don't even know what's a good type to return. InputStream?)
Thanks
P.S. By "file" I mean "path", e.g. "data/texture1.png".
Doing #1 and #3 is pretty easy. Doing #2 (just looking in the current JAR only) is much harder as it requires you figuring out what JAR you
If you wanted to check the filesystem first, otherwise load from classpath, it would be something like:
public java.io.InputStream loadByName(String name) {
java.io.File f = new java.io.File(name);
if (f.isFile()) {
return new FileInputStream(f);
} else {
return getClass().getResource(name);
}
}
If you want to prefer loading from the same JAR file first, you will need to figure out where it is. Check out Determine which JAR file a class is from for more info on figuring out the JAR file you want to load the resource from.
A URLClassLoader should be able to load both and try the file path first if the file path is on the class path ahead of the jar.
Regarding your comments:
I know that relative jar URLs don't
work. That's why the Spring guys came
up with the Resource abstraction.
Read about it here.
You might want to check the answers
to this Question: Loading a file
relative to the executing jar
file. The problem is similar to
yours.
Current jar file and current directory are not concepts in the JVM like they are when you're running a shell script. You would need to specify a directory to be used for loading the files that you're interested in, such as with a system property while executing the JVM:
java -Ddirectory.to.scan=/home/aib
Then retrieve this property:
String dir = System.getProperty("directory.to.scan");
Now when talking about JAR files, all JAR files specified explicitly on the classpath when you start the JVM are loaded by the ClassLoader. You can get the ClassLoader of a specific class by:
InputStream is = <Your class>.class.getClassLoader().getResourceAsStream("binary file");
Note that any jar file loaded by the current class loader is searched.
I'm trying to load a custom log.properties file when my application is started.
My properties file is in the same package as my main class, so I assumed that the -Djava.util.logging.config.file=log.properties command line parameter should get the properties file loaded.
But the properties are only loaded when i specify a full absolute path to the properties file. Any suggestions how to use a relative path?
You can dynamically load java.util.logging properties files from a relative path very easily. This is what I put inside a static {} block in my Main class. Put your logging.properties file in the default package and you can access it very easily with the following code.
final InputStream inputStream = Main.class.getResourceAsStream("/logging.properties");
try
{
LogManager.getLogManager().readConfiguration(inputStream);
}
catch (final IOException e)
{
Logger.getAnonymousLogger().severe("Could not load default logging.properties file");
Logger.getAnonymousLogger().severe(e.getMessage());
}
Java logging doesn't search your whole hard disk for a file; there are very simple rules how files are looked up. You want Java to see that the two files belong to each other but you didn't say so anywhere. Since Java sees no connection between the properties file and your class other than that they are in the same folder on your disk, it can't find the file.
-Djava.util.logging.config.file=log.properties only works if the file log.properties is in the current directory of the Java process (which can be pretty random). So you should use an absolute path here.
An alternate solution would be to move the file logging.properties into $JAVA_HOME/lib/ (or edit the file which should be there). In that case, you don't need to set a System property.
util logging does not load from classpath, it needs an absolute path which is why other logging packages like log4j are far easier to configure and better for web apps where it's a pain to get abs paths.
this is not explained at all in the java.util.logging.LogManager doco.