Java properties not loading - java

I am trying to set up a java .properties file outside of the packaged jar. This is my code to load it:
public static final String FILENAME = "test.properties";
public static void load() throws IOException {
FileInputStream fis = null;
try {
props = new Properties();
fis = new FileInputStream(FILENAME);
props.load(fis);
System.out.println("Properties successfully loaded: "+props);
validateProperties();
} catch (FileNotFoundException e) {
System.err.println("Properties file not found. Creating...");
new File(FILENAME).createNewFile();
//fill with default properties
System.out.println("Properties file successfully created");
} finally {
if (fis != null) try {fis.close();} catch(Exception e) {}
}
}
Unfortunately, when I run this, I get the following output:
Properties successfully loaded: {}
Here is test.properties:
#no comment
#Sun Jun 23 19:21:45 CDT 2013
port=55142
handSize=10
maxPlayers=8
timeout=1500
I have confirmed, by manually reading and printing, that the FileInputStream is reading from the correct file. So why aren't my properties loading?
EDIT: Here is some code which loads the contents of the properties file directly:
public static void test() throws IOException {
FileInputStream fis = new FileInputStream(FILENAME);
byte[] b = new byte[fis.available()];
fis.read(b);
String text = new String(b);
System.out.println(text);
}
and it outputs:
#no comment
#Sun Jun 23 19:21:45 CDT 2013
port=55142
handSize=10
maxPlayers=8
timeout=500
so the FIS must be reading from the correct file.
EDIT 2: Ok, so I don't know what the problem was, but I restarted eclipse and now it's working. Very sorry to have wasted your time.

Check what line separator your java system uses. Eg:
System.out.println((int)System.getProperty("line.separator").charAt(0));
On UNIX that will give 10, which is newline \n, on Windows that will be 13 (eg: the first char of \r\n).
I think your java code is reading the file using Windows encoding, yet the property file is edited in UNIX, hence everyting appears to be in "one single line" -- which will result in empty properties because your first line is commented

As your properties file is not present in the classpath so you cannot read it without giving the proper path. There are multiple approaches to read an external properties file from a jar. One of the simplest way is to use the -D switch to define a system property on a java command line. That system property may contain a path to your properties file.
E.g
java -cp ... -Dmy.app.properties=/path/to/test.properties my.package.App
Then, in your code you can do :
public static final String FILENAME = "test.properties";
public static void load() throws IOException {
FileInputStream fis = null;
String propPath = System.getProperty(FILENAME);
try {
props = new Properties();
fis = new FileInputStream(propPath);
props.load(fis);
System.out.println("Properties successfully loaded: "+props);
validateProperties();
} catch (FileNotFoundException e) {
System.err.println("Properties file not found. Creating...");
new File(propPath ).createNewFile();
//fill with default properties
System.out.println("Properties file successfully created");
} finally {
if (fis != null) try {fis.close();} catch(Exception e) {}
}
}

When there is no absolute path mentioned, JVM tries to load resources from the JVM & project classpath. In your case, empty output signifies that JVM is trying to load property file from classpath but the file is not there.
Solutions:
1) Either place your property file in your classpath
2) Or mention absolute path to property file.

A ResourceBundle offers a very easy way to access key/value pairs in a properties file in a Java...
You can refer following.
http://www.avajava.com/tutorials/lessons/how-do-i-read-a-properties-file-with-a-resource-bundle.html
You can directly specify your properties file name while loading the bundle when it is present in the same folder as your jar/classes.

Related

How to attach file to jar that can be edited inside this jar?

I am making a program that works with MySQL database,for now i store URL, login, password e.t.c as public static String. Now i need to make it possible to work on another computer, so database adress will vary, so i need a way to edit it inside programm and save. I would like to use just external txt file, but i don't know how to point it's location.
I decided to make it using Property file, i put it in src/res folder. It work correct while i'm trying it inside Intellij Idea, but when i build jar (artifact) i get java.io.FileNotFoundException
I tried two ways:
This one was just copied
private String getFile(String fileName) {
StringBuilder result = new StringBuilder("");
//Get file from resources folder
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
System.out.println(file.length());
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
result.append(line).append("\n");
}
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
return result.toString();
}
System.out.println(obj.getFile("res/cfg.txt"));</code>
And second one using Properties class:
try(FileReader reader = new FileReader("src/res/cfg.txt")) {
Properties properties = new Properties();
properties.load(reader);
System.out.println(properties.get("password"));
}catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
In both ways i get java.io.FileNotFoundException. What is right way to attach config file like that?
Since the file is inside a .JAR, it can't be accessed via new File(), but you can still read it via the ClassLoader:
Properties properties = new Properties();
try (InputStream stream = getClass().getResourceAsStream("/res/cfg.txt")) {
properties.load(stream);
}
Note that a JAR is read-only. So this approach won't work.
If you want to have editable configuration, you should place your cfg.txt outside the JAR and read it from the filesystem. For example like this:
Properties properties = new Properties();
File appPath = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile();
try (InputStream stream = new FileInputStream(new File(appPath, "cfg.txt"))) {
properties.load(stream);
}
There are multiple places your can place your configuration options, and a robust deployment strategy will utilize some (or all) of the following techniques:
Storing configuration files in a well known location relative to the user's home folder as I mentioned in the comments. This works on Windows (C:\Users\efrisch), Linux (/home/efrisch) and Mac (/Users/efrisch)
File f = new File(System.getProperty("user.home"), "my-settings.txt");
Reading environment variables to control it
File f = new File(System.getenv("DEPLOY_DIR"), "my-settings.txt");
Using a decentralized service such as Apache ZooKeeper to store your database settings
Use Standalone JNDI
(or the JNDI built-in to your deployment target)
Use a Connection Pool

FileInputStream loads second last version of a file

I have a simple method that reloads config after file has been modified.
private Properties loadCustomProperties(File config) throws IOException {
Properties properties = new Properties();
try (FileInputStream inStream = new FileInputStream(config)) {
properties.load(inStream);
}
return properties;
}
Now if I run this code from IDE (Intellij) everything works fine, but when run using Spring bootstrap jar it loads 2nd last version of the file. So basicaly if I have inital value prop=1, then change it to prop=2, I still have prop=1 loaded. If I change it to prop=3, I end up with loaded prop=2 and so on.
System is Ubuntu 18.04.
Properties look like this:
cache.size=1000
And the expected output is to get latest version of the file.
I suggest you building an utility method for reading the single property, so you can easly load all properties that you need 1 by 1, something like (in my example the config file is named config.properties):
public static String getPropertyValue(String property) throws IOException {
Properties prop = new Properties();
String propFileName = "config.properties";
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(propFileName);
if (inputStream != null) {
prop.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
return prop.getProperty(property);
}
So if in your config.properties file you put something like
cache.size=1000
when you call getPropertyValue("cache.size") you will get 1000

java FileInputStream cannot find file

I'm very new at coding java and I'm having a lot of difficulty.
I'm suppose to write a program using bufferedreader that reads from a file, that I have already created named "scores.txt".
So I have a method named processFile that is suppose to set up the BufferedReader and loop through the file, reading each score. Then, I need to convert the score to an integer, add them up, and display the calculated mean.
I have no idea how to add them up and calculate the mean, but I'm currently working on reading from the file.
It keeps saying that it can't fine the file, but I know for sure that I have a file in my documents named "scores.txt".
This is what I have so far...it's pretty bad. I'm just not so good at this :( Maybe there's is a different problem?
public static void main(String[] args) throws IOException,
FileNotFoundException {
String file = "scores.txt";
processFile("scores.txt");
//calls method processFile
}
public static void processFile (String file)
throws IOException, FileNotFoundException{
String line;
//lines is declared as a string
BufferedReader inputReader =
new BufferedReader (new InputStreamReader
(new FileInputStream(file)));
while (( line = inputReader.readLine()) != null){
System.out.println(line);
}
inputReader.close();
}
There are two main options available
Use absolute path to file (begins from drive letter in Windows or
slash in *.nix). It is very convenient for "just for test" tasks.
Sample
Windows - D:/someFolder/scores.txt,
*.nix - /someFolder/scores.txt
Put file to project root directory, in such case it will be visible
to class loader.
Place the scores.txt in the root of your project folder, or put the full path to the file in String file.
The program won't know to check your My Documents folder for scores.txt
If you are using IntelliJ, create an input.txt file in your package and right click the input.txt file and click copy path. You can now use that path as an input parameter.
Example:
in = new FileInputStream("C:\\Users\\mda21185\\IdeaProjects\\TutorialsPointJava\\src\\com\\tutorialspoint\\java\\input.txt");
Take the absolute path from the local system if you'r in eclipse then right-click on the file and click on properties you will get the path copy it and put as below this worked for me In maven project keep the properties file in src/main/resources `
private static Properties properties = new Properties();
public Properties simpleload() {
String filepath="C:/Users/shashi_kailash/OneDrive/L3/JAVA/TZA/NewAccount/AccountConnector/AccountConnector-DEfgvf/src/main/resources/sample.properties";
try(FileInputStream fis = new FileInputStream(filepath);) {
//lastModi = propFl.lastModified();
properties.load(fis);
} catch (Exception e) {
System.out.println("Error loading the properties file : sample.properties");
e.printStackTrace();
}
return properties;
}`

File.createNewFile() failing in java (Ubuntu 12.04)

I am trying to createNewFile() in java.I have written down the following example.I have compiled it but am getting a run time error.
import java.io.File;
import java.io.IOException;
public class CreateFileExample
{
public static void main(String [] args)
{
try
{
File file = new File("home/karthik/newfile.txt");
if(file.createNewFile())
{
System.out.println("created new fle");
}else
{
System.out.println("could not create a new file");
}
}catch(IOException e )
{
e.printStackTrace();
}
}
}
It is compiling OK.The run time error that I am getting is
java.io.IOException: No such file or directory
at java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:947)
at CreateFileExample.main(CreateFileExample.java:16)
some points here
1- as Victor said you are missing the leading slash
2- if your file is created, then every time you invoke this method "File.createNewFile()" will return false
3- your class is very platform dependent (one of the main reasons why Java is powerful programming language is that it is a NON-PLATFORM dependent), instead you can detect a relative location throw using the System.getProperties() :
// get System properties :
java.util.Properties properties = System.getProperties();
// to print all the keys in the properties map <for testing>
properties.list(System.out);
// get Operating System home directory
String home = properties.get("user.home").toString();
// get Operating System separator
String separator = properties.get("file.separator").toString();
// your directory name
String directoryName = "karthik";
// your file name
String fileName = "newfile.txt";
// create your directory Object (wont harm if it is already there ...
// just an additional object on the heap that will cost you some bytes
File dir = new File(home+separator+directoryName);
// create a new directory, will do nothing if directory exists
dir.mkdir();
// create your file Object
File file = new File(dir,fileName);
// the rest of your code
try {
if (file.createNewFile()) {
System.out.println("created new fle");
} else {
System.out.println("could not create a new file");
}
} catch (IOException e) {
e.printStackTrace();
}
this way you will create your file in any home directory on any platform, this worked for my windows operating system, and is expected to work for your Linux or Ubuntu as well
You're missing the leading slash in the file path.
Try this:
File file = new File("/home/karthik/newfile.txt");
That should work!
Actually this error comes when there is no directory "karthik" as in above example and createNewFile() is only to create file not for directory use mkdir() for directory and then createNewFile() for file.

Writing to a properties file does not work

I want to write into a *.properties file. Thats my code how I do this:
properties = loadProperties("user.properties");//loads the properties file
properties.setProperty(username, password);
try {
properties.store(new FileOutputStream("user.properties"), null);
System.out.println("Wrote to propteries file!" + username + " " + password);
I do not get an exception, but I also do not get the output written into the file.
Here is also my file-structure:
I appreciate your answer!!!
UPDATE
I load my properties file with:
InputStream in = ClassLoader.getSystemResourceAsStream(filename);
My question is, how to load it from a specific path?
Here is my "new" File Structure:
Here is my testing code:
#Test
public void fileTest() throws FileNotFoundException, IOException {
File file = null;
Properties props = new Properties();
props.setProperty("Hello", "World");
URL url = Thread.currentThread().getContextClassLoader()
.getResource("exceptions/user.properties");
try {
file = new File(url.toURI().getPath());
assertTrue(file.exists());
} catch (URISyntaxException e) {
e.printStackTrace();
}
props.store(new FileOutputStream(file), "OMG, It werks!");
}
It does creates and rewrites a file in my target/classes/exceptions directory (in a maven/eclipse proyect) so I guess it really works, but of course that is not tested in a JAR file.
Here is the file:
#OMG, It werks!
#Sat Nov 10 08:32:44 CST 2012
Hello=World
Also, check this question: How can i save a file to the class path
So maybe what you want to do never will work.

Categories

Resources