I have a method that sets a few properties using Java Properties if the config file does not exists in the local drive. However the bad thing I found out was even if I change a few properties in my code, the method just checks if the file exists and does not update the file with new properties.
The other condition is the user might have overwritten one of the property in the config file. So the method that sets the property should not overwrite the values on the config file with my code.
Here is what I did
private void setDefaultConfig() {
try {
if (!checkIfFileExists(configFile)) {
setProperty(configFile, "cfgFile", "cfg.xml");
setProperty(configFile, "type", "emp");
setProperty(configFile, "url", "www.google.com");
}
} catch (Exception e) {
e.printStackTrace();
}
}
setPropertyMethod just sets the property on the specified file.
Now if I add another property in my method the user won't get the new property because I'm just checking if the file exists.
For Eg : If the user changes the "url" property to have "www.yahoo.com" then my code in the setDefaultConfig method should not replace the value with "www.google.com"
Is there any method that can handle this situation?
protected void setProperty(String fileName, String property, String value) {
Properties prop = new Properties();
FileOutputStream fileOut = null;
FileInputStream fileIn = null;
try {
File file = new File(fileName);
if(checkIfFileExists(fileName)) {
fileIn = new FileInputStream(file);
prop.load(fileIn);
}
prop.setProperty(property, value);
fileOut = new FileOutputStream(fileName);
prop.store(fileOut, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (fileOut != null) {
try {
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Related
I am trying access a properties file in a library. The problem is that the file is located in the META-INF folder of the application which is using my library. I am currently using:
private static final String CONFIG_FILE = "config.properties";
private Properties getConfigFile(){
InputStream input = null;
Properties config = new Properties();
input = this.getClass().getResourceAsStream(CONFIG_FILE);
if(input == null){
System.out.println("*****************************************INPUT NULL DEST**************************************");
return null;
}
try {
config.load(input);
return config;
} catch (IOException io) {
if(input!=null){
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return config;
}`
But withoud any success. I have tried to rename the constant to "META-INF/config.properties" and still getting null.
I am trying write to a csv file. After the execution of the code bellow the csv file is still empty.
File is in folder .../webapp/resources/.
This is my dao class:
public class UserDaoImpl implements UserDao {
private Resource cvsFile;
public void setCvsFile(Resource cvsFile) {
this.cvsFile = cvsFile;
}
#Override
public void createUser(User user) {
String userPropertiesAsString = user.getId() + "," + user.getName()
+ "," + user.getSurname() +"\n";;
System.out.println(cvsFile.getFilename());
FileWriter outputStream = null;
try {
outputStream = new FileWriter(cvsFile.getFile());
outputStream.append(userPropertiesAsString);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public List<User> getAll() {
return null;
}
}
This is a part of beans.xml.
<bean id="userDao" class="pl.project.dao.UserDaoImpl"
p:cvsFile="/resources/users.cvs"/>
Program compiles and doesn't throw any exceptions but CSV file is empty.
If you're running your app in IDE, the /webapp/resources used for running app will differ from the /webapp/resources in your IDE. Try to log full path to file and check there.
try using outputStream.flush() as the final statement in the first of the try block.
I think you're looking at the wrong file. If you specify an absolute path /resources/users.cvs, then it probably won't be written into the a folder relative to the webapp. Instead, it will be written to /resources/users.cvs
So the first step is to always log an absolute path to make sure the file is where you expect it.
Try with this code, it will at least tell you where the problem lies (Java 7+):
// Why doesn't this method throw an IOException?
#Override
public void createUser(final User user)
{
final String s = String.format("%s,%s,%s",
Objects.requireNonNull(user).getId(),
user.getName(), user.getSurname()
);
// Note: supposes that .getFile() returns a File object
final Path path = csvFile.getFile().toPath().toAbsolutePath();
final Path csv;
// Note: this supposes that the CSV is supposed to exist!
try {
csv = path.toRealPath();
} catch (IOException e) {
throw new RuntimeException("cannot locate CSV " + path, e);
}
try (
// Note: default is to TRUNCATE the destination.
// If you want to append, add StandardOpenOption.APPEND.
// See javadoc for more details.
final BufferedWriter writer = Files.newBufferedWriter(csv,
StandardCharsets.UTF_8);
) {
writer.write(s);
writer.newLine();
writer.flush();
} catch (IOException e) {
throw new RuntimeException("write failure", e);
}
}
I have written the code bellow to check if a properties file exists and has the required properties. If it exists it prints the message that the file exists and is intact, if not then it creates the properties file with the required properties.
What I wanted to know is, is there a more elegant way of doing this or is my way pretty much the best way? Also the minor problem that I'm having is that with this way it doesn't check for extra properties that should not be there, is there a way to do that?
Summary of my requirements:
Check if the file exists
Check if it has the required properties
Check if it has extra properties
Create the file with the required properties if it doesn't exist or if there are extra or missing properties
Source files and Netbeans Project download
Source:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
public class TestClass {
public static void main(String[] args) {
File propertiesFile = new File("config.properties");
if (propertiesFile.exists() && propertiesExist(propertiesFile)) {
System.out.println("Properties file was found and is intact");
} else {
System.out.println("Properties file is being created");
createProperties(propertiesFile);
System.out.println("Properties was created!");
}
}
public static boolean propertiesExist(File propertiesFile) {
Properties prop = new Properties();
InputStream input = null;
boolean exists = false;
try {
input = new FileInputStream(propertiesFile);
prop.load(input);
exists = prop.getProperty("user") != null
&& prop.getProperty("pass") != null;
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return exists;
}
public static void createProperties(File propertiesFile)
{
Properties prop = new Properties();
OutputStream output = null;
try {
output = new FileOutputStream(propertiesFile);
prop.setProperty("user", "username");
prop.setProperty("pass", "password");
// save properties to project root folder
prop.store(output, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
this is my way. (not sure if more elegant, but it can be an inspiration/different aproach)
Try/catch should be enough to see if the file exists or not
try {
loading files etc...
} catch (FileNotFoundException e) {
throw new MojoExecutionException( "[ERROR] File not found", e );
} catch (IOException e) {
throw new MojoExecutionException( "[ERROR] Error reading properties", e );
}
Code that checks your loaded prop:
Properties tmp = new Properties();
for(String key : prop.stringPropertyNames()) {
if(tmp.containsKey(key)){
whatever you want to do...
}
}
I use tmp, a new properties variable, to compare with ,but the key variable will hold a string so in the if statement you can compare it to array of strings and the way you do it is up to you.
My problem is in the following code.
The problem is that when I call the alreadyUser(String username) if the file doesn't exist on the system already, it gives the FileNotFoundException. I want to get over this error and I can not figure it out.
So at startup of the app the system asks for uname and pass. Then the alreadyUser method is called and it gives the error if the file is not already created hardly (I create it manually for example). And the next time I start the program if the file is already there it must not be switched with new, because the old data will be gone ofc :)
public final class TinyBase {
final static String FILENAME = "KEYVALUES.txt";
static FileOutputStream fos = null;
static FileInputStream fis = null;
protected static void createUser(String username, String password)
protected static boolean loadUser(String username, String password)
protected static boolean alreadyUser(String username) {
String encode = new String(username);
String compare = null;
boolean flag = false; // true - ok no such user ; false - fail username
// already in use
try {
/* ERROR IS HERE */
fis = new FileInputStream(FILENAME);
/* ERROR IS HERE */
byte[] buffer = new byte[fis.available()];
while (fis.read(buffer) != -1) {
compare = new String(buffer);
if (compare.contains(encode)) {
flag = true;
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
return flag;
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
Check if the file exists using -
File f = new File(filePathString);
if(f.exists()) { /* do something */ }
I guess, what you need according to your snapshot, is to handle FileNotFoundCase properly :
// ....
} catch (FileNotFoundException e) {
Log.d("no settings for the user - assuming new user");
flag = true;
}
BTW, you need to fix your finally block, in case of prior exception your fis may be null, so to avoid NullPointerException you may need an extra check :
if (fis != null) {
fis.close();
}
UPDATE
Here is sketch of what you may need based on my understanding of your problem :
// ... somewhere at startup after username/pass are given
// check if file exists
if (new File(FILENAME).isFile() == false) { // does not exist
fos = new FileOutputStream(FILENAME); // will create
// file for you (not subfolders!)
// write content to your file
fos.close();
}
// by this point file exists for sure and filled with correct user data
alreadyUser(userName);
Hmm simple task but how do i load properties file from path that is not in my class path?
for example: i have simple java file that i execute like this :
foo.jar d:/sample/dir/dir/app1.properties
and in the code i do :
public boolean InitConfig(String propePath) {
prop = new Properties();
try {
InputStream in = this.getClass().getClassLoader().getResourceAsStream(propePath);
prop.load(in);
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
where propePath is : d:/sample/dir/dir/app1.properties
and InputStream in is always null.
why does this happen?
The only resources that can be loaded by Classloader.getResourceAsStream are ones in the class (loaders) path. To read properties from an arbitrary path use one of the load functions of the Properties class itself.
final Properties props = new Properties();
props.load(new FileInputStream(filePath));