UTF-8 encoded Java String into Properties - java

I have a single UTF-8 encoded String that is a chain of key + value pairs that is required to be loaded into a Properties object. I noticed I was getting garbled characters with my intial implementation and after a bit of googling I found this Question which indicated what my problem was - basically that Properties is by default using ISO-8859-1. This implementation looked like
public Properties load(String propertiesString) {
Properties properties = new Properties();
try {
properties.load(new ByteArrayInputStream(propertiesString.getBytes()));
} catch (IOException e) {
logger.error(ExceptionUtils.getFullStackTrace(e));
}
return properties;
}
No encoding specified, hence my problem. To my question, I can't figure out how to chain / create a Reader / InputStream combination to pass to Properties.load() that uses the provided propertiesString and specifies the encoding. I think this is mostly due to my inexperience in I/O streams and the seemingly vast library of IO utilities in the java.io package.
Any advice appreciated.

Use a Reader when working with strings. InputStreams are really meant for binary data.
public Properties load(String propertiesString) {
Properties properties = new Properties();
properties.load(new StringReader(propertiesString));
return properties;
}

private Properties getProperties() throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("your file");
InputStreamReader inputStreamReader = new InputStreamReader(input, "UTF-8");
Properties properties = new Properties();
properties.load(inputStreamReader);
return properties;
}
then usage
System.out.println(getProperties().getProperty("key"))

Try this:
ByteArrayInputStream bais = new ByteArrayInputStream(propertiesString.getBytes("UTF-8"));
properties.load(bais);

Related

Sending UTF-8 message to Xpages

I have an XPages application for Swedish users.
When I am sending a message to the facescontext via
msg = propStrings.getProperty("gen_CustDateDecided") ;
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.addMessage("msgBox", new javax.faces.application.FacesMessage(msg));
The text for the that is broadcasted resides on a properties file, with UTF-8 encoding.
When loading the properties file I make sure it is read in UTF-format:
private Properties getPropertiesFromFile(String fileName) {
Properties prop = new Properties();
try {
InputStream is = FacesContextEx.getCurrentInstance().getExternalContext().getResourceAsStream(fileName);
BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
prop.load(r);
} catch (Exception e) {
XspOpenLogUtil.logEvent(null, null, fileName, Level.WARNING, null);
}
return prop;
}
The text that appears on the messages control on the Xpage:
Senaste beslutsdatum i kundkommittén
The text in the properties file:
gen_CustDateDecided=Senaste beslutsdatum i kundkommittén
What have I done wrong?
Property files are not encoded as UTF-8. They are ISO 8859-1. You need to encode them accordingly. Easiest is to just use a few lines in a standalone Java class to save properties. Takes care of encoding.
More details here:
How to use UTF-8 in resource properties with ResourceBundle

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

Assigning a destination for properties file in a java program

Sorry if this seems like a newbie question and im sure its just a little thing i need to change but it seems like my program cannot locate the destination for a properties file i coded in.
here is my code
public String metrics() throws IOException {
String result = "";
Properties prop = new Properties();
String propFileName = "C:\\Users\\JChoi\\Desktop\\config.properties";
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
prop.load(inputStream);
if (inputStream == null) {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
// get the property value and print it out
String Metrics = prop.getProperty("Metrics");
result = Metrics;
System.out.println(result);
return result;
}
I get a nullpointerexception error everytime i run the code but however, when i put the properties file in the resources folder and edit the string name to...
String propFileName = "config.properties";
works fine...any suggestions?
EDIT:
String result = "";
Properties prop = new Properties();
String propFileName = "C:\\Users\\JChoi\\Desktop\\config.properties";
FileInputStream fileInputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
prop.load(fileInputStream);
SOLVED!
String propFileName = "C:\\Users\\JChoi\\Desktop\\googlebatchfile\\config.properties";
BufferedInputStream inputStream;
FileInputStream fileInputStream = new FileInputStream(propFileName);
inputStream = new BufferedInputStream(fileInputStream);
If you know the full path to a file, then do not try to open it using a classpath search (which is what getResourceAsStream() does).
Instead open the file using an inputsteam that takes a path.
Here is some code:
FileInputStream inputStream = new FileInputStream(propFileName);
The following might be a better technique (I'm not sure with property loading):
BufferedInputStream inputStream;
FileInputStream fileInputStream = new FileInputStream(propFileName);
inputStream = new BufferedInputStream(fileInputStream);
You are attempting to load a file using a classpath-based input stream but specifying a filepath.
This:
getClass().getClassLoader().getResourceAsStream(propFileName);
Will attempt to search the classpath starting at the root (based on whatever the classloader considers the root).
If you want to load a file from outside the classpath, you probably just want to use something like a FileInputStream instead.

Java Properties.store is deleting other entries

I am trying to modify a config file in Java using Properties. I try to modify two of the multiple entries like this:
Properties properties = new Properties();
FileInputStream fin = null;
FileOutputStream fout = null;
fin = new FileInputStream(mCallback.getConfFile());
fout = new FileOutputStream(mCallback.getConfFile());
properties.load(fin);
properties.setProperty(Wrapper.GAME_PATH_KEY, (String)gamePathText.getText());
properties.setProperty(Wrapper.GAME_TYPE_KEY, (String)selectedGame.getSelectedItem());
properties.store(fout, null);
But when I check the file after the result I find out that the whole file was overwritten, leaving only these two entries. This is an android app though I guess it's not relevant to the problem here. What I am doing wrong?
You have to read all properties and then modify the ones you want. After that you have to write all to file. You cannot do only an item modification. The Properties API doesn't provide that functionality to modify.
Edit:
Interchange these two statements-
fout = new FileOutputStream(mCallback.getConfFile());
properties.load(fin);
You should load first before you create a file with the same name.
From Properties:
public void store(OutputStream out,
String comments)
throws IOException
Writes this property list (key and element pairs) in this Properties table to the output > stream in a
format suitable for loading into a Properties table using the
load(InputStream) method.
Properties from the defaults table of this
Properties table (if any) are not written out by this method.
This method outputs the comments, properties keys and values in the
same format as specified in store(Writer), with the following
differences:
So, Load the data first, then set the required data, then store it.
Properties prop =new Properties();
prop.load(new FileInputStream(filename));
prop.setProperty(key, value);
prop.store(new FileOutputStream(filename),null);
The previous poster was kind of right, just not at the right place.
You need to open the FileOutputStream after you've loaded the properties otherwise it clears the file's content.
Properties properties = new Properties();
FileInputStream fin = null;
FileOutputStream fout = null;
fin = new FileInputStream(mCallback.getConfFile());
// if fout was here, the file would be cleared and reading from it would produce no properties
properties.load(fin);
properties.setProperty(Wrapper.GAME_PATH_KEY, (String)gamePathText.getText());
properties.setProperty(Wrapper.GAME_TYPE_KEY, (String)selectedGame.getSelectedItem());
fout = new FileOutputStream(mCallback.getConfFile());
properties.store(fout, null);

Java properties not loading

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.

Categories

Resources