Properties file reads old data when jar is executed from command line - java

I have created a java application that copies data from properties file (resources-> settings -> config.properties) and uses it. At one point the properties file values are updated and the code has to use the new values. The code works fine when executed from Netbeans. But when I execute ti from the dist folder after build, the old values get loaded everytime even when I change the the properties file. The properties file gets updated but the values used are still the old ones.
Code to write properties file
File f = new File(System.getProperty("user.dir") + "\\resources\\settings\\config.properties");
try (OutputStream output = new FileOutputStream(f)) {
Properties prop = new Properties();
// set the properties value
prop.setProperty("xml", xmlFileTextBox.getText());
// save properties to project root folder.
prop.store(output, null);
} catch (IOException exception) {
exception.printStackTrace();
}
Code to read values in properties file
try {
Properties prop = new Properties();
String propFileName = "settings/config.properties";
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(propFileName)) {
if (inputStream != null) {
prop.load(inputStream);
xmlFileTextBox.setText(prop.getProperty("xml"));
}
inputStream.close();
}
} catch (Exception e) {
System.out.println("Exception: " + e);}

The file you are reading from is a file that is packaged with your application and not the file you are saving to.
This code, getClass().getClassLoader().getResourceAsStream(propFileName)), gives you a resource from the classpath.
You need to create the File in the same way as when you save the properties, then get the InputStream from that File.
If you want to have the defaults in your original properties file you might need to check for null in the "save file" and if it don't have data then read from your default resourse file.

Related

Android studio, File.properties deleted after reopening the app

I saved a File.properties in this.getFilesDir() + "Data.propertie".
In the app, I save the data that the user wrote, but when i open the app, all the data (or the file) that I saves from the previous time has been deleted.
Example:
// Store
for (Map.Entry<String,String> entry : MainActivity.Notes.entrySet()) { // Put all data from Notes in properties to store later
properties.put(entry.getKey(), entry.getValue());
}
try { properties.store(new FileOutputStream(this.getFilesDir() + "data.properties"), null); } // Store the data
catch (IOException e) { e.printStackTrace(); } // Error exception
// Load the map
Properties properties = new Properties(); // Crate properties object to store the data
try {
properties.load(new FileInputStream(this.getFilesDir() + "data.proprties")); } // Try to load the map from the file
catch (IOException e) { e.printStackTrace(); } // Error exception
for (String key : properties.stringPropertyNames()) {
Notes.put(key, properties.get(key).toString()); // Put all data from properties in the Notes map
}
// Can load the data
You can see that i saved the data in the file, and I can load it, but when I open the app, the data has been deleted
There is a way to write in the file and save the data that i write to the next time I open the app?
First off Context.getFilesDir returns a File object. This File represents the private data directory of your app.
Then you do getFilesDir() + "foo" which will implicitly call toString() on the File instance. File.toString() is equivalent to File.getPath which does not necessarily return a trailing slash.
This means, if getFilesDir() returns a File at /data/app, your properties file will become /data/appdata.properties which is not in your data Folder and cannot be written to.
Instead, to get a File within a directory you can create a new File instance with that directory. e.g:
File propertiesFile = new File(this.getFilesDir(), "data.properties");
// use propertiesFile for FileOutputStream/FileInputStream etc.
This ensures that your properties file is within that directory and prevents any issues from file separators

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

Android Studio write to .properties file

I followed Where to put own properties file in an android project created with Android Studio? and I got an InputStream which reads from my .properties file successfully. However, I can't write to that .properties file, as there is no similar method to getBaseContext().getAssets().open ("app.properties") which returns an OutputStream. I have also read Java Properties File appending new values but this didn't seem to help me, my guess is my file name for the file writer is wrong but I also tried "assets\userInfo.properties" which also doesn't work.
My .properties file is in src\main\assets\userInfo.properties
Properties props = new Properties();
InputStream inputStream = null;
try{
inputStream = getBaseContext().getAssets().open("userInfo.properties");
props.load(inputStream);
props.put("name", "smith");
FileOutputStream output = new FileOutputStream("userInfo.properties"); //this line throws error
props.store(output, "This is overwrite file");
String name = props.getProperty("name");
Log.d(TAG, "onCreate: PROPERTIES TEST NAME CHANGE: " + name);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Current code throws this error:
java.io.FileNotFoundException: userInfo.properties (Read-only file system)
You can't write to the assets folder, as it is inside the APK which is read-only.
Use internal or external storage instead
You can't write to the assets folder. If you want to update your properties file, you'll have to put them some place else. If you want the initial version in the assets or raw folder, just copy it to the default files dir when the app is first used, then read from/write to it there.

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.

Reading Properties file every time in the execution in Java

I have to read properties file "MyProperty.properties" from "ReadProp.java" class given my the following directory structure of my "war" file I am going to deploy.
MyApp.war
| ----MyProps
| |--MyProperty.properties
|---WEB-INF |
|--classes
|---ReadProp.java
I am going to deploy this "war" file in "Sun portal server". But I should not change any of this directory structure because of the requirement specification.
I am reading this file in the following way
String path = servletContext.getRealPath("/MyProps/MyProperty.properties"); System.out.println("path: " + path);
Properties prop = new Properties();
try {
prop.load(new FileInputStream(path));
);
} catch (Exception e) {
e.printStackTrace();
}
String name= prop.getProperty("name");
It is working fine. but the problem is if I change properties file after loading the application the changes are not reflecting.
I may change the properties file anytime how to do If I want that changes should be reflected . I mean the application should load the properties file everytime in the exexcutio
You won't see changes unless you bounce the app server.
A better choice would be to put the .properties file in your /WEB-INF/classes folder and read it from the CLASSPATH using getResourceAsStream().
You don't say where you're reading the code. You might have to implement a Timer task to periodically wake up and reload the .properties file.
You might also try a WatchService if you're using JDK 7:
Auto-reload changed files in Java
You need to use java 7 WatchService for that Example Link
I got the answer:
String path = servletContext.getRealPath("/MyProps/MyProperty.properties");
System.out.println("path: " + path);
Properties prop = new Properties();
try {
File f = new File(path);
FileInputStream fis = new FileInputStream(f);
prop.load(fis);
}
catch (Exception e) {
e.printStackTrace();
}
The newer way to do this is:
Path path;
try {
path = Paths.get("MyProperty.properties");
if (Files.exists(path)) {
props = new Properties();
props.load(Files.newInputStream(path));
}
} catch (IOException e) {
e.printStackTrace();
}

Categories

Resources