JAVA Rewrite/store only specified key value of properties - java

Let say i have property file test.properties.
There are already defined some key/values pairs e.g:
key1=value1
key2=value2
key3=value3
I change in memory some value of these properties (let say only one key's value). I would like to store changes into property file, but to store really only changed key/value => not rewrite whole file.
Is that possible?
Any implementation of some library to I could achieve something like that?

String fileName = "C:\\test\\test.txt";
File f = new File(fileName);
InputStream is = new FileInputStream(f);
Properties p = new Properties();
p.load(is);
p.setProperty("key3","value4");
OutputStream os = new FileOutputStream(f);
p.store(os,"comments");
But I think this will overwrite the entire properties file.

Look at java.util.prefs.Preferences
EDIT:
This is a Java utility class that does what you seem to want -- store key/value pairs (only strings as keys) without having to (re)write an entire file of them to change one value. Java has implemented them with system-dependent backing so they're portable.

Related

How can I modify a particular line in a file without deleting the existing data using Java?

I need to change the values in a file which has more than 30 lines and each line has a data like:
ENABLE_TLS=true
PSWD_MIN_LENGTH=8
Here, let us consider this as a key and value pair, and I needed to change only the value for the 2nd line alone, without deleting the 1st line. Can someone help me how can I do this??
I have tried bufferedwriter, but it is replacing all the lines.
My expectation is:
I need to modify only a particular key's value and the remaining lines should not get deleted
Your description of the data sounds like Java Properties. If you are certain that all the data in that file takes the form key=value you could read it in as a Properties object, update the value for the key in question, and write it back to the file.
Properties properties = new Properties();
try (FileInputStream inputStream = new FileInputStream("/path/to/file")) {
properties.load(inputStream);
}
properties.put("PSWD_MIN_LENGTH", 12);
try (FileOutputStream outputStream = new FileOutputStream("/path/to/file")) {
properties.store(outputStream, null);
}
BEWARE: there is no guarantee that the order of the key/value entries in the file will be maintained (they probably won't). If you are looking for a Properties implementation that will maintain the order, maybe this SO answer will do the trick (UNTESTED!) How maintain the order of keys in Java properties file?

Which method I can use in Java for configuration file?

Which method I can use in Java for configuration files, to read and write specific lines and strings? For example (config.ini):
mysql_host: localhost
mysql_user: user
or
mysql_host = localhost
mysql_user = user
You can use ini4j library.
Ini ini = new Ini(new File(filename));
java.util.prefs.Preferences prefs = new IniPreferences(ini);
And then you can go ahead fetch nodes with prefs.node("mysql_host").
Have a look at Java Properties:
Properties are configuration values managed as key/value pairs. In
each pair, the key and value are both String values. The key
identifies, and is used to retrieve, the value, much as a variable
name is used to retrieve the variable's value. For example, an
application capable of downloading files might use a property named
"download.lastDirectory" to keep track of the directory used for the
last download.
To manage properties, create instances of java.util.Properties. This
class provides methods for the following:
loading key/value pairs into a Properties object from a stream,
retrieving a value from its key,
listing the keys and their values,
enumerating over the keys,
and saving the properties to a stream.
You can load properties files with
Properties applicationProps = new Properties();
try (FileInputStream in = new FileInputStream("appProperties")) {
applicationProps.load(in);
}
and store them with
try (FileOutputStream out = new FileOutputStream("appProperties")) {
applicationProps.store(out, "---No Comment---");
}

java encode String to UTF

I want to display characters (Chinese or other language) from property file on Windows box.
Let's say I read a property server.location=上海的位置 from System property, which is set when server is started.
I tried to do this
new String(locationStr.getBytes(System.getProperty("file.encoding")), "UTF-8");
This works with Linux, but couldn't get it working on Windows.
Following is summarized snipet, without syntax of how the System Property is set
URL fileURL = new URL("file:filePathAndName");
InputStream iStream = fileURL.openStream () ;
Properties prop = new Properties();
prop.load(iStream);
//Enumerate over prop and set System.setProperty (key, value);
Reading property as System.getProperty("server.location")
This is done centrally for all property files, hence modifying anything while reading or setting specific encoding could affect others, hence not advisable.
Also tried to encode using URLEncoder.encode but didn't help.
I do not see any specific encoding set. Java uses UTF-16, on Windows the encoding is 'Cp1252'. What am I missing here?
Any help to make this work or throw some light is appreciated. Also tried to go through existing questions, but the answers didn't apply directly hence creating new question.
Thanks
Edit:
Couldn't convert the obtained String to UTF-8. Somehow convinced people to read properties in way Joop mentioned and retrieve the String properly
String/char/Reader/Writer in java contain Unicode text. Binary data, byte[], InputStream/OutputStream must be associated with an encoding to be convertable to text, String.
It seems your Properties file is in UTF-8. Then specify a fixed encoding when loading the properties.
InputStream iStream = fileURL.openStream();
Reader reader = new BufferedReader(new InputStreamReader(iStream, StandardCharsets.UTF_8));
Properties prop = new Properties();
prop.load(reader);
Here the InputStreamReader bridges the transition from binary data to (Unicode) text by a conversion specifying the encoding of the InputStream.
Properties prop = new Properties();
InputStream input = null;
String filename = "config.properties";
input = ClassName.class.getClassLoader().getResourceAsStream(filename);
//loading properties
prop.load(input);
//getting the properties
System.out.println(prop.getProperty("propertyname1"));
System.out.println(prop.getProperty("propertyName2"));
System.out.println(prop.getProperty("propertyName3"));
or you can enumerate over the proerties
Enumeration e = prop.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
System.out.println(key + " -- " + prop.getProperty(key));
}
this is how you should actually get properties from a property file
and you dont have to worry about the utf-8 characters.

I am trying to store File path(4 files) and Files metadata to hashmap.how to do that? i am using Tika API

Using TikaApi i am trying to read xlsx file path and xlsx file metadata but i am not sure how to store files path and metadata into hashmap for further access or reading from hashmap .
Please help !
Use a HashMap with the File as key and Metadata as value (or viceversa, depends on what you want). Then put the file and the corresponding metadata in the hashmap.
HashMap<File, Metadata> hashMap = new HashMap<File, Metadata>();
hashMap.put(file, metadata);
Also, it would be a better practice to use List<String> l = new ArrayList<String>(); (or even better, List<File>) instead of List l = new ArrayList();
PD: You have some unindented code in the for loop. Indenting it might make it more readable.

How can I create cache map in this situation?

For example, I've got some place in my code, that receives many files (many of them are identical) from disk and, further, unmarshalls them.
final File configurationFile = getConfigurationFile();
FileOutputStream fileOutputStream = new FileOutputStream(configurationFile);
Marshaller.marshal(configObject, fileOutputStream);
Obviously, I can create a special cache map for them to increase performance (in order not to unmarshall identical files again and again). For my case, HashMap implementation will be enough.
The question is: what key for that should I use?
configurationFile.hashCode() is very bad for this?
Thanks for all your answers!
Use the canonical path instead of the absolute path (explanation of the difference) and put it in a HashSet. Sets don't allow duplicated values. If you try to add a value that already exists, it will return false, otherwise true.
Example code (untested):
Set<String> filesMarshalled= new HashSet<>();
...
final File configurationFile = getConfigurationFile();
if (filesMarshalled.add(configurationFile.getCanonicalPath())) {
//not marshalled yet
FileOutputStream fileOutputStream = new FileOutputStream(configurationFile);
Marshaller.marshal(configObject, fileOutputStream);
}
You can also use hashset without actually worrying about key.
if(hashset.add(file)) {
// do unmarshling;
} else {
//do nothing
}
Hashset.add() method return true if an object can be added.
If you try to add duplicate entry then it will return false since duplicacy is not allowed in sets.
...identical files again and again...
What is identical?
If the file content decides, you may use a hash of the file content (e.g. MD5, SHA1, SHA256) as the key.
If the file name must be identical, simply use the file name as the key.
If the file path, then use the full path of the file as the key (File.getCanonicalPath()).

Categories

Resources