I'm trying to change some values in my config.properties file.There is change in values when I set them but it doesn't get saved. here is my code
public class Config {
String filename = "config.properties";
public void displayConfig() throws IOException {
Properties prop = new Properties();
InputStream input = null;
input = getClass().getClassLoader().getResourceAsStream(filename);
if (input == null) {
System.out.println("unable to find " + filename);
return;
}
prop.load(input);
System.out.println();
System.out.println(prop);
Enumeration<?> e = prop.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String value = prop.getProperty(key);
System.out.println(key + " : " + value);
}
return;
}
public void setConfig() throws Exception {
File filename = new File("config.properties");
Properties prop = new Properties();
FileInputStream in = new FileInputStream(filename);
prop.load(in);
in.close();
FileOutputStream out = new FileOutputStream("config.properties");
prop.setProperty("db", "csv");
prop.setProperty("user", "tej");
prop.setProperty("password", "54321");
prop.store(out, null);
out.close();
System.out.println();
System.out.println(prop);
}
}
and the output when I call displayConfig,setConfig,displayConfig is like
{user=localhost, db=dtcc, password=12345}
db : dtcc
user : localhost
password : 12345
{user=tej, db=csv, password=54321, key=value}
{user=localhost, db=dtcc, password=12345}
db : dtcc
user : localhost
password : 12345
Well, that's quite expected, since displayConfig() doesn't load its properties from the same location as setConfig().
displayConfig() loads them from the resource config.properties at the root of the classpath, and setConfig loads and saves them in a file in the current directory.
BTW; even if the current directory happens to be in the classpath, I think getResourceAsStream() caches the stream content the first time it's called.
Choose your poison: either you want readable and writable files, and you should use file IO, or you want read-only resources loaded from the classpath, and you should use getResource[AsStream]. Don't mix both.
Related
I'm trying to create an instance of a file to parse html records from a property value. the problem is in the url of the file that I must put in the file properties, here is my example :
the correspondance code for reading file :
public void extraxtElementWithoutId() {
Map<String,List<List<Element>>> uniciteIds = new HashMap<String,List<List<Element>>>();
FileReader fileReader = null;
Document doc = null;
try {
fileReader = new FileReader(new ClassPathResource(FILEPROPERTYNAME).getFile());
Properties prop = new Properties();
prop.load(fileReader);
Enumeration<?> enumeration = prop.propertyNames();
List<List<Element>> fiinalReturn = null;
while (enumeration.hasMoreElements()) {
String path = (String) enumeration.nextElement();
System.out.println("Fichier en question : " + prop.getProperty(path));
URL url = getClass().getResource(prop.getProperty(path));
System.out.println(url.getPath());
File inputFile = new File(url.getPath());
doc = Jsoup.parse(inputFile, "UTF-8");
//fiinalReturn = getListofElements(doc);
//System.out.println(fiinalReturn);
fiinalReturn = uniciteIds.put("Duplicat Id", getUnicityIds(doc));
System.out.println(fiinalReturn);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try{
fileReader.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
Thank you in advance,
Best Regards.
You are making a very common mistake for line -
URL url = getClass().getResource(prop.getProperty(path));
Try with property value as ( by removing src ) - /testHtmlFile/test.html and so on. Don't change code.
UrlEnterer1=/testHtmlFile/test.html instead of preceding it with src.
prop.getProperty(path) should be as per your build path location for the file. Check your build directory as how these files are stored. These are not stored under src but directly under build directory.
This answer explains a little bit about path value for file reading from class path.
Also, as a side note ( not related to question ) , try not doing prop.getProperty(path) but directly injecting property value in your class using org.springframework.beans.factory.annotation.Value annotation.
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
We recently had to set up one of the tomcat servers from scratch. Tomcat version is 8.0.20. Deploying a war file, now System.getProperty("mode") returns "null" where it should return PREPROD.
It should read this "mode" from a mode.properties file which is located in the webapps directory. The two lines commented out show another part of code that does not work anymore on the new tomcat server. I replaced it with code that should work.
//String pathOfWebInf = sce.getServletContext().getRealPath("WEB-INF");
//String pathOfLocalhostFile = pathOfWebInf + File.separator + "classes"
// + File.separator;
String pathOfLocalhostFile = this.getClass().getResource("/").getPath();
String mode = System.getProperty("mode");
String fileName = "localhost-oracle.properties." + mode;
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword("xxx");
Properties dbProps = new EncryptableProperties(encryptor);
try
{
InputStream is = new FileInputStream(pathOfLocalhostFile + fileName);
dbProps.load(is);
} catch (Exception e)
{
throw new IOException("Could not read properties file " + pathOfLocalhostFile + fileName);
}
System.properties is related to all properties in the Computer where the JVM is running... there is no mode key defined there, that is why you get null as value....
check out all the properties in the pc by doing:
final Properties props = System.getProperties();
props.list(System.out);
and verify yourself, there is no mode key in that map...
You have to load mode.properties first, like this way
private Properties mode=null;
mode = new Properties();
mode.load(new FileInputStream(pathtoMODE));
String mode = mode.getProperty("mode");
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.
This question already has answers here:
Platform independent paths in Java
(8 answers)
Closed 3 years ago.
I have a java swing database application which needs to be run on Windows and Linux. My database connection details are stored in a XML file and I load them.
This application can load this properties on Linux properly but it is not working on Windows.
How do I load files on multiple platforms properly using Java?
This is the code:
PropertyHandler propertyWriter = new PropertyHandler();
List keys = new ArrayList();
keys.add("ip");
keys.add("database");
Map localProps = propertyWriter.read(keys, "conf" + File.separatorChar + "properties.xml", true);//if false load from the local properties
//get properties from the xml in the internal package
List seKeys = new ArrayList();
seKeys.add("driver");
seKeys.add("username");
seKeys.add("password");
Map seProps = propertyWriter.read(seKeys, "conf" + File.separatorChar + "properties.xml", true);
String dsn = "jdbc:mysql://" + (String) localProps.get("ip") + ":3306/" + (String) localProps.get("database");
jDBCConnectionPool = new JDBCConnectionPool((String) seProps.get("driver"), dsn, (String) seProps.get("username"), (String) seProps.get("password"));
File reader method:
public Map read(List properties, String path, boolean isConfFromClassPath)
{
Properties prop = new Properties();
Map props = new HashMap();
try {
if (isConfFromClassPath) {
InputStream in = this.getClass().getClassLoader().getResourceAsStream(path);
prop.loadFromXML(in);
for (Iterator i = properties.iterator(); i.hasNext();) {
String key = (String) i.next();
props.put(key, prop.getProperty(key));
}
in.close();
} else {
FileInputStream in = new FileInputStream(path);
prop.loadFromXML(in);
for (Iterator i = properties.iterator(); i.hasNext();) {
String key = (String) i.next();
props.put(key, prop.getProperty(key));
}
in.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return props;
}
If the file is in a jar file and accessed by the classpath then you should always use /.
The JavaDocs for the ClassLoader.getResource say that "The name of a resource is a '/'-separated path name that identifies the resource."
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)
I'm not sure if there is the proper way, but one way is:
File confDir = new File("conf");
File propFile = new File(confDir, "properties.xml");
But in a scenario as simple as yours, I would just use /
If it's a resource located in classpath, we can load it with following snippet:
getClass().getClassLoader().getResourceAsStream(
"/META-INF/SqlQueryFile.sql")));
You can load all files on multiple platforms without any trouble.
Kindly use Matcher.quoteReplacement(File.separator) for replacing the slash.
It will works for every platform.
String fileLocation = "/src/service/files";
fileLocation = fileLocation.replaceAll("/",Matcher.quoteReplacement(File.separator));
assuming that your file is in conf/properties.xml on Linux and conf\properties.xml on Windows,
use File.pathSeparator instead of File.separator