Hi this post is related to my old post. But in this I have achieved much.
I am using FileBasedConfigurationBuilder class of Apache common configuration API for updating property file in java. Below is my code:
FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<PropertiesConfiguration>(
PropertiesConfiguration.class)
.configure(new Parameters().properties().setFileName("test.properties")
.setThrowExceptionOnMissing(true));
PropertiesConfiguration config = builder.getConfiguration();
config.setProperty("Id", "3");
builder.save();
System.out.println("config.properties updated Successfully!!");
Now one of my key have value like
C\://ABC.net\\:1010.
After modification it becomes
C\\://ABC.net\\:1010. Means it single backslash is converting to two single backslash. Previously I was using common configuration jar 1.10 it that forwardslash also getting change. Now I have used common configuration version
commons-configuration2-2.0.jar. By this version only problem in backslash.
Can any one suggested how to avoid this? I need that after modification single backslash should not convert to doublebackslash.Please note that I don't want to change the property file.
I was following below post to reach till here.
PropertiesConfiguration - Using "/" in Property value
In a properties file, the : character is escaped with a single backslash, which is what seems to be happening in your question.
See this question How do you escape colon (:) in Properties file?
which points to the Properties documentation
Related
I want to store a URL in a properties file. This is the URL:
jdbc\:sqlserver\://dummydata\\SHARED
When programming this in Java, I obviously need to escape the backslashes. So my code ends up looking like this
properties.setProperty("db", "jdbc\\:sqlserver\\://dummydata\\\\SHARED");
The issue with this is that the properties file is saving the String URL and including the backslashes used for escaping, which is an incorrect URL. I was hoping that Java would interpret the backslashes used for escaping so that only the correct URL is saved. Is there a way to achieve this?
You're correct that a property value with : needs to escape the colons in a .properties text file, but you're not writing that text file directly.
You are giving the value to a Properties object using setProperty(), and presumably writing that to a text file using store(), and the store() method will escape the values as needed for you.
You should give the value you want to Properties, and forget about the encoding rules of the text file. Properties will handle all needed encoding. Since the value you want to give is jdbc:sqlserver://dummydata\SHARED, you write a string literal "jdbc:sqlserver://dummydata\\SHARED"
Example
String db = "jdbc:sqlserver://dummydata\\SHARED";
System.out.println(db); // To see actual string value
Properties properties = new Properties();
properties.setProperty("db", db);
try (FileWriter out = new FileWriter("test.properties")) {
properties.store(out, null);
}
Output
jdbc:sqlserver://dummydata\SHARED
Content of test.properties
#Tue Jun 11 11:54:24 EDT 2019
db=jdbc\:sqlserver\://dummydata\\SHARED
As you can see, the store() method has escaped the : and \ for you.
If you save the properties as an XML file instead, there's no need to escape anything, and Properties won't.
Example
try (FileOutputStream out = new FileOutputStream("test.xml")) {
properties.storeToXML(out, null);
}
Content of test.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="db">jdbc:sqlserver://dummydata\SHARED</entry>
</properties>
Properties.store() escapes backslashes, there is no way around it. I guess my first question is why is this an issue? Are you reading the file in any other way than using Properties.load(). If not they you don't need to worry about it as the load function will remove the escape characters.
properties.load(file);
System.out.println(properties.get("db"));
// output: jdbc\:sqlserver\://dummydata\\SHARED
As an aside are you sure you the URL is correct? Shouldn't you be storing it as properties.setProperty("jdbc:sqlserver://dummydata\SHARED")?
In the documentation for load, it says the following:
The method does not treat a backslash character, \, before a non-valid escape character as an error; the backslash is silently dropped. For example, in a Java string the sequence "\z" would cause a compile time error. In contrast, this method silently drops the backslash. Therefore, this method treats the two character sequence "\b" as equivalent to the single character 'b'.
This means that two backslashes will be treated as a single one because it's not a valid escape sequence. Loading this string should work just fine:
C:\\path\\to\\file
I am saving the path of a file as using Properties in Java into a config file.
this.adb = adb.getAbsolutePath();
this.prop.setProperty("adb", this.adb);
//save config to project root folder
this.prop.store(new FileOutputStream("config"), null);
The contents of config file after saving are:
adb=C\:\\Program Files\\Genymobile\\Genymotion\\tools\\adb.exe
How do I save it without the escape characters so that it can be easy for a user to modify the path manually without having to type in escape characters.
I also tried to save the config file manually without using escape characters, but the program read the property as:
C:Program FilesGenymobileGenymotion oolsadb.exe
And the code for reading properties from the config file is:
prop.load(new FileInputStream("config"));
this.adb = prop.getProperty("adb");
java.util.Properties.store uses backslash to escape special characters (e.g. equal sign in properties keys), so a literal backslash itself will need to be escaped \\. If this behaviour is not what you want, don't use java.util.Properties, roll out your own utility Properties class it should be a simple exercise. If your not sure what an escape character is check this Wikipedia page.
The relevant code in Properties class (saveConvert method)
if (aChar == '\\') {
outBuffer.append('\\'); outBuffer.append('\\');
continue;
}
Since I do not know of a better solution, I am currently writing small Java classes to process .properties file to merge them, remove duplicate properties, override properties, etc. (I need to process many files and a huge number of properties).
org.apache.commons.configuration.PropertiesConfiguration works great for reading a properties file (using org.apache.commons.configuration.AbstractFileConfiguration.load(InputStream, String), however if I rewrite the file using org.apache.commons.configuration.AbstractFileConfiguration.save(File), I have two problems:
the original layout and comments are lost. I am going to try the PropertiesConfigurationLayout, which is supposed to help here (see How to overwrite one property in .properties without overwriting the whole file?) and post the results
the properties are slightly modified. Accents é and è are rewritten as unicode characters (\u00E9), which I do not want. Afaik .properties files are generally ISO-8859-1 (and I think mine are), so escaping shouldn't be necessary.
Specifying the encoding when calling org.apache.commons.configuration.AbstractFileConfiguration.load(InputStream, String) does not make a difference, because when it is not specified, the same encoding is used by default anyway (private static final String DEFAULT_ENCODING = "ISO-8859-1";). What could I do about that ?
Doing some tests I think you can do what you want, using CombinedConfiguration plus a OverrideCombiner. Basically the properties will be merged automatically and the trick for the layout is to get the layout from one of the loaded files:
CombinedConfiguration props = new CombinedConfiguration();
final PropertiesConfiguration defaultsProps = new PropertiesConfiguration(new File("/tmp/default.properties"));
final PropertiesConfiguration customProps = new PropertiesConfiguration(new File("/tmp/custom.properties"));
props.setNodeCombiner(new OverrideCombiner());
props.addConfiguration(customProps); //first should be loaded the override values
props.addConfiguration(defaultsProps); // last your 'default' values
PropertiesConfiguration finalFile = new PropertiesConfiguration();
finalFile.append(props);
PropertiesConfigurationLayout layout = new PropertiesConfigurationLayout(finalFile, defaultsProps.getLayout()); //here we copy the layout from the 'base file'
layout.save(new FileWriter(new File("/tmp/app.properties")));
The issue with the encoding I don't know if its possible to find a solution.
I was working with an app that loads a .properties file with java.util.Properties like this:
Properties _properties = new Properties();
_properties.load(new FileInputStream("app.properties"));
The properties file (initially) was this:
app=myApp
dbLogin=myDbLogin
version=0.9.8.10
server=1
freq=10000
stateGap=360000
The strange thing was that when I called _properties.getProperty("app"), it always returned null, however I could load all of the other properties without any issues. I solved the problem by adding a comment to the top of the properties file, then everything worked fine.
My question is: Why does Java do this? I can't seem to find any documentation about this, and it seems counter-intuitive.
Thanks to #KonstantinV.Salikhov and #pms for their help in hunting this down; I decided to post the answer that was discovered to save people hunting through the comments.
The problem was that my file was the wrong encoding, as mentioned here: http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html
The load(Reader) / store(Writer, String) methods load and store properties from and to a character based stream in a simple line-oriented format specified below. The load(InputStream) / store(OutputStream, String) methods work the same way as the load(Reader)/store(Writer, String) pair, except the input/output stream is encoded in ISO 8859-1 character encoding.
(Emphasis mine).
I changed the encoding of the properties file to ISO-8859-1 and everything worked.
Java does not handle the BOM correctly – you can see it in the properties as key. It is possible to save the file UTF-8 but without BOM. In vim for instance
:set nobomb
See vim wiki
Using
<replaceregexp byline="true" flags="g" file="${someFIle}"
match = "[\\]"
replace = "/"/>
I can easily replace all the \ with /.
But
Suppose the text is:
Other A\B\C
Some C\D\E
Other ...
Other ...
...
How to replace the "\" with "/" in the second line which has prefix "Some", but not other lines:
Other A\B\C
Some C/D/E
...
replaceregexp does not have options to skip lines.
Your problem cannot be merely solved by a single regex. You need to do something more complex.
1) Read properties only with the specified prefix and save them to variable. This can be done with propertyregex.
2) Read all other properties and save them somewhere.
3) Replace \ with whatever you want in the properties which contain the prefix.
4) Write the modified properties with the properties without the prefix into a file replacing the original file.
5) Enjoy :-)
Try to do these steps one by one. If you still have questions let me know.