I am currently using the Apache commons configuration library to write and read data from a file. I am able to save the key value pair colors=hello to the user..properties file, but when i try to read the value is get the below exception.
Exception in thread "main" java.lang.IllegalArgumentException: 'hello' does not contain an equals sign
at org.apache.commons.configuration.AbstractConfiguration.getProperties(AbstractConfiguration.java:625)
at org.apache.commons.configuration.AbstractConfiguration.getProperties(AbstractConfiguration.java:579)
at com.code.prep.CommonsMain.readProperties(CommonsMain.java:21)
at com.code.prep.CommonsMain.main(CommonsMain.java:12)
The code is as below
package com.code.prep;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
public class CommonsMain {
public static void main(String[] args) {
CommonsMain main = new CommonsMain();
main.readProperties();
// main.writeProperties();
}
public void readProperties(){
PropertiesConfiguration config = new PropertiesConfiguration();
try {
config.load("user.properties");
System.out.println(config.getProperties("colors"));
} catch (ConfigurationException e) {
e.printStackTrace();
}
}
public void writeProperties(){
PropertiesConfiguration config = new PropertiesConfiguration();
try {
config.load("user.properties");
config.setProperty("colors", "hello");
config.save("user.properties");
} catch (ConfigurationException e) {
e.printStackTrace();
}
}
}
The Jars in the class path are:
commons-configuration-1.9.jar
commons-lang-2.4.jar
commons-logging-1.1.1.jar
user.properties contains
colors = hello
user = thejavamonk
You should not be using
config.getProperties("colors")
but
config.getProperty("colors")
"getProperties(code)" is looking for (multiple) lines in your user.properties file of the form:
code key=val
so it's expecting your code as it stands to have lines like :
colors foreground=black
colors background=white
etc.
This does not look like library issue. Open your file and check whether the data is actually available. From you code it looks like you are doing -
main.readProperties();
// main.writeProperties();
Why would there be any data unless you write it? Call writeProperties() method first and then read it back.
Related
I am coming to an issue where I am trying to check if output folder is there and if not create one in my code below. So, I tried doing that way as shown in my code but I dont know if its the proper a way of doing it? can you please advise. thanks for the help.
here is my code:
String outputFolder2 = Printer.getOutputFolder();
File outFileTwo = new File(outputFolder2);
if (!outFileTwo.exists()) {
if (!outFileTwo.mkdir()) {
System.out.println("Failed to make directory for: " + outputFolder2);
}
}
To check if the directory exists:
Files.isDirectory(Paths.get("/the/path"))
To create dir if not exists:
Files.createDirectories(Paths.get("/the/path"))
Simply use
dirPathFileObj.mkdir();
From java.io.File;
If the method detects that no such directory exists, it will automatically create one. Otherwise, it will simply do nothing in terms of File creation.
It's recommended to use the nio package for new code that interacts with files -- it's faster, and easier to code for. Here's how I would write that code, in the form of a junit test that I ran to verify it:
#Test
public void testSomething() {
Path dirPath = Paths.get("C:/I/do/not/exist");
Path filePath = dirPath.resolve("newFile.txt");
try {
assertFalse(Files.exists(dirPath));
dirPath = createDirectories(dirPath);
filePath = Files.createFile(filePath);
assertTrue(Files.exists(filePath));
} catch (IOException iox) {
iox.printStackTrace();
} finally {
try {
Files.deleteIfExists(filePath);
Files.deleteIfExists(dirPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
This will create C:\I\do\not\exist\newFile.txt, then delete C:\I\do\not\exist, (leaving C:\I\do\not\). For production code, you'd want to remove the asserts and fill in those catch clauses
I am trying to access a properties file from the src/main/resources folder but when I try to load the file using a relative path it is not getting updated. But it is working fine for an absolute path.
I need the dynamic web project to work across all platforms.
public static void loadUsers() {
try(
FileInputStream in = new FileInputStream("C:\\Users\\SohamGuha\\Documents\\work-coding\\work-coding\\src\\main\\resources\\users.properties")) {
// write code to load all the users from the property file
// FileInputStream in = new FileInputStream("classpath:users.properties");
users.load(in);
System.out.println(users);
in.close();
}
catch(Exception e){
e.printStackTrace();
}
First of all you are using Spring, at least that is what the tags at the bottom say. Secondly C:\\Users\\SohamGuha\\Documents\\work-coding\\work-coding\\src\\main\\resources\\users.properties is the root of your classpath. Instead of loading a File use the Spring resource abstraction.
As this is part of the classpath you can simply use the ClassPathResource to obtain a proper InputStream. This will work regardless of which environment you are in.
try( InputStream in = new ClassPathResource("users.properties").getInputStream()) {
//write code to load all the users from the property file
//FileInputStream in = new FileInputStream("classpath:users.properties");
users.load(in);
System.out.println(users);
} catch(Exception e){
e.printStackTrace();
}
NOTE: you are already using a try with resources so you don't need to close the InputStream that is already handled for you.
Changing things inside your application simply won't work, as this would mean you could change resources (read classes) in your jar which would be quite a security risk! If you want something to be changable you will have to make it a file outside of the classpath and directly on the file-system.
Try the following code
import java.io.FileInputStream;
import java.io.IOException;
public class LoadUsers {
public static void main(String[] args) throws IOException {
try(FileInputStream fis=new FileInputStream("src/main/resources/users.properties")){
Properties users=new Properties();
users.load(fis);
System.out.println(users);
}catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
How to read the values from properties file in java script?
I goggling about it but not satisfied.Please share me some samples or links. My application develops by jsp-servlet, eclipse LUNA and Windows7.
Javascript is executed on the client side and cannot access local files (except the html5 web storage).
If you want to access properties which are defined in a properties file on the server side you have two options:
Server side parsing
Read the properties file at the server side and write the values to the html response as JS values
// output a property as JS value to the client. Make sure this is inside a
// <script> tag
void printProperty(Properties properties, String key) {
Sytem.out.println("var " + key + "='"properties.getProperty("key") + "'");
}
Client side parsing (more complex)
Make the properties file available through an URL (http:/.../conf.properties)
Read the file via ajax
Parse the properties file
You can read property file in many way, below is one of the way. Good Link
config.properties
dbpassword=password
database=localhost
dbuser=mkyong
App.java
package com.mkyong.properties;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class App {
public static void main(String[] args) {
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("config.properties");
// load a properties file
prop.load(input);
// get the property value and print it out
System.out.println(prop.getProperty("database"));
System.out.println(prop.getProperty("dbuser"));
System.out.println(prop.getProperty("dbpassword"));
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Google Links
suppose I put a file a.txt in package com.xyz and the try access it like following. Will it work?
Hi All,
import com.xyz.*;
public class Hello
{
File f = new File("a.txt");
...
}
It is not working for me. Is there any workaround?
Use Class.getResource() or Class.getResourceAsStream(). see for example the Sun demo source at http://jc.unternet.net/src/java/com/sun/WatermarkDemo/WatermarkDemo.java
I will offer the same answer as jcomeau_ictx, but a lot shorter (around 30 lines in one file as opposed to >380 in 1 source file of 5), ..and with a screenshot. ;)
import javax.swing.*;
import java.net.URL;
class GetResource {
GetResource() {
Class cl = this.getClass();
final URL url = cl.getResource( cl.getName() + ".java" );
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JEditorPane ep = new JEditorPane();
try {
ep.setPage(url);
JScrollPane sp = new JScrollPane(ep);
sp.setPreferredSize(new java.awt.Dimension(400,196));
JOptionPane.showMessageDialog(null, sp);
} catch(Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(
null,
e.getMessage() + " See trace for details.");
}
}
});
}
public static void main(String[] args) {
new GetResource();
}
}
Based on your responses to the comments above. If you are looking for a work around, just specify the path to the .txt file on the file system. Putting it in a package does not help.
new File ("a.txt")
looks for a file on the the file system and not within a package.
Please also read the javadocs on File:
http://download.oracle.com/javase/6/docs/api/java/io/File.html
However I do not see the rationale in putting the file inside a package unless you would want to use it as a resource. In which case #jcomeau_ictx has the right solution
It's depend on your class path of java from where you can run this class. If both are in same place then it will work. Then no need to define path in file. But the file was not in the classpath dir then must be define path of that file otherwise file not found.
I'm trying to configure the Java Logging API's FileHandler to log my server to a file within a folder in my home directory, but I don't want to have to create those directories on every machine it's running.
For example in the logging.properties file I specify:
java.util.logging.FileHandler
java.util.logging.FileHandler.pattern=%h/app-logs/MyApplication/MyApplication_%u-%g.log
This would allow me to collect logs in my home directory (%h) for MyApplication and would rotate them (using the %u, and %g variables).
Log4j supports this when I specify in my log4j.properties:
log4j.appender.rolling.File=${user.home}/app-logs/MyApplication-log4j/MyApplication.log
It looks like there is a bug against the Logging FileHandler:
Bug 6244047: impossible to specify driectorys to logging FileHandler unless they exist
It sounds like they don't plan on fixing it or exposing any properties to work around the issue (beyond having your application parse the logging.properties or hard code the path needed):
It looks like the
java.util.logging.FileHandler does not
expect that the specified directory
may not exist. Normally, it has to
check this condition anyway. Also, it
has to check the directory writing
permissions as well. Another question
is what to do if one of these check
does not pass.
One possibility is to create the
missing directories in the path if the
user has proper permissions. Another
is to throw an IOException with a
clear message what is wrong. The
latter approach looks more consistent.
It seems like log4j version 1.2.15 does it.
Here is the snippet of the code which does it
public
synchronized
void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
throws IOException {
LogLog.debug("setFile called: "+fileName+", "+append);
// It does not make sense to have immediate flush and bufferedIO.
if(bufferedIO) {
setImmediateFlush(false);
}
reset();
FileOutputStream ostream = null;
try {
//
// attempt to create file
//
ostream = new FileOutputStream(fileName, append);
} catch(FileNotFoundException ex) {
//
// if parent directory does not exist then
// attempt to create it and try to create file
// see bug 9150
//
String parentName = new File(fileName).getParent();
if (parentName != null) {
File parentDir = new File(parentName);
if(!parentDir.exists() && parentDir.mkdirs()) {
ostream = new FileOutputStream(fileName, append);
} else {
throw ex;
}
} else {
throw ex;
}
}
Writer fw = createWriter(ostream);
if(bufferedIO) {
fw = new BufferedWriter(fw, bufferSize);
}
this.setQWForFiles(fw);
this.fileName = fileName;
this.fileAppend = append;
this.bufferedIO = bufferedIO;
this.bufferSize = bufferSize;
writeHeader();
LogLog.debug("setFile ended");
}
This piece of code is from FileAppender, RollingFileAppender extends FileAppender.
Here it is not checking whether we have permission to create the parent folders, but if the parent folders is not existing then it will try to create the parent folders.
EDITED
If you want some additional functionalily, you can always extend RollingFileAppender and override the setFile() method.
You can write something like this.
package org.log;
import java.io.IOException;
import org.apache.log4j.RollingFileAppender;
public class MyRollingFileAppender extends RollingFileAppender {
#Override
public synchronized void setFile(String fileName, boolean append,
boolean bufferedIO, int bufferSize) throws IOException {
//Your logic goes here
super.setFile(fileName, append, bufferedIO, bufferSize);
}
}
Then in your configuration
log4j.appender.fileAppender=org.log.MyRollingFileAppender
This works perfectly for me.
To work around the limitations of the Java Logging framework, and the unresolved bug: Bug 6244047: impossible to specify driectorys to logging FileHandler unless they exist
I've come up with 2 approaches (although only the first approach will actually work), both require your static void main() method for your app to initialize the logging system.
e.g.
public static void main(String[] args) {
initLogging();
...
}
The first approach hard-codes the log directories you expect to exist and creates them if they don't exist.
private static void initLogging() {
try {
//Create logging.properties specified directory for logging in home directory
//TODO: If they ever fix this bug (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6244047) in the Java Logging API we wouldn't need this hack
File homeLoggingDir = new File (System.getProperty("user.home")+"/webwars-logs/weblings-gameplatform/");
if (!homeLoggingDir.exists() ) {
homeLoggingDir.mkdirs();
logger.info("Creating missing logging directory: " + homeLoggingDir);
}
} catch(Exception e) {
e.printStackTrace();
}
try {
logger.info("[GamePlatform] : Starting...");
} catch (Exception exc) {
exc.printStackTrace();
}
}
The second approach could catch the IOException and create the directories listed in the exception, the problem with this approach is that the Logging framework has already failed to create the FileHandler so catching and resolving the error still leaves the logging system in a bad state.
As a possible solution I think there are 2 approaches (look at some of the previous answers). I can extend a Java Logging Handler class and write my own custom handler. I could also copy the log4j functionality and adapt it to the Java Logging framework.
Here's an example of copying the basic FileHandler and creating a CustomFileHandler see pastebin for full class:
The key is the openFiles() method where it tries to create a FileOutputStream and checking and creating the parent directory if it doesn't exist (I also had to copy package protected LogManager methods, why did they even make those package protected anyways):
// Private method to open the set of output files, based on the
// configured instance variables.
private void openFiles() throws IOException {
LogManager manager = LogManager.getLogManager();
...
// Create a lock file. This grants us exclusive access
// to our set of output files, as long as we are alive.
int unique = -1;
for (;;) {
unique++;
if (unique > MAX_LOCKS) {
throw new IOException("Couldn't get lock for " + pattern);
}
// Generate a lock file name from the "unique" int.
lockFileName = generate(pattern, 0, unique).toString() + ".lck";
// Now try to lock that filename.
// Because some systems (e.g. Solaris) can only do file locks
// between processes (and not within a process), we first check
// if we ourself already have the file locked.
synchronized (locks) {
if (locks.get(lockFileName) != null) {
// We already own this lock, for a different FileHandler
// object. Try again.
continue;
}
FileChannel fc;
try {
File lockFile = new File(lockFileName);
if (lockFile.getParent() != null) {
File lockParentDir = new File(lockFile.getParent());
// create the log dir if it does not exist
if (!lockParentDir.exists()) {
lockParentDir.mkdirs();
}
}
lockStream = new FileOutputStream(lockFileName);
fc = lockStream.getChannel();
} catch (IOException ix) {
// We got an IOException while trying to open the file.
// Try the next file.
continue;
}
try {
FileLock fl = fc.tryLock();
if (fl == null) {
// We failed to get the lock. Try next file.
continue;
}
// We got the lock OK.
} catch (IOException ix) {
// We got an IOException while trying to get the lock.
// This normally indicates that locking is not supported
// on the target directory. We have to proceed without
// getting a lock. Drop through.
}
// We got the lock. Remember it.
locks.put(lockFileName, lockFileName);
break;
}
}
...
}
I generally try to avoid static code but to work around this limitaton here is my approach that worked on my project just now.
I subclassed java.util.logging.FileHandler and implemented all constructors with their super calls. I put a static block of code in the class that creates the folders for my app in the user.home folder if they don't exist.
In my logging properties file I replaced java.util.logging.FileHandler with my new class.