How to load a properties file from the root directory? - java

I am currently loading a properties file like this:
private Properties loadProperties(String filename) throws IOException{
InputStream in = ClassLoader.getSystemResourceAsStream(filename);
if (in == null) {
throw new FileNotFoundException(filename + " file not found");
}
Properties props = new Properties();
props.load(in);
in.close();
return props;
}
However, at the moment my file lays at the scr\user.properties path.
But when I want to write to a properties file:
properties.setProperty(username, decryptMD5(password));
try {
properties.store(new FileOutputStream("user.properties"), null);
System.out.println("Wrote to propteries file!" + username + " " + password);
That piece of code generates me a new file at the root folder level of my project.
BUT I want to have one file to write\read.
Therefore how to do that?
PS.: When I want to specify the path I get "Not allowed to modify the file..."

The reason a new file is created because you are trying to create a new file when you are writing. You should first get handle to the user.properties that you want to write to as File object and then try to write to it.
The code would look something along the lines of
properties.setProperty(username, decryptMD5(password));
try{
//get the filename from url class
URL url = ClassLoader.getSystemResource("user.properties");
String fileName = url.getFile();
//write to the file
props.store(new FileWriter(fileName),null);
properties.store();
}catch(Exception e){
e.printStacktrace();
}

Related

Create directory in Java but don't throw error if it already exists [duplicate]

The condition is if the directory exists it has to create files in that specific directory without creating a new directory.
The below code only creates a file with the new directory but not for the existing directory . For example the directory name would be like "GETDIRECTION":
String PATH = "/remote/dir/server/";
String fileName = PATH.append(id).concat(getTimeStamp()).append(".txt");
String directoryName = PATH.append(this.getClassName());
File file = new File(String.valueOf(fileName));
File directory = new File(String.valueOf(directoryName));
if (!directory.exists()) {
directory.mkdir();
if (!file.exists() && !checkEnoughDiskSpace()) {
file.getParentFile().mkdir();
file.createNewFile();
}
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(value);
bw.close();
Java 8+ version:
Files.createDirectories(Paths.get("/Your/Path/Here"));
The Files.createDirectories() creates a new directory and parent directories that do not exist. This method does not throw an exception if the directory already exists.
This code checks for the existence of the directory first and creates it if not, and creates the file afterwards. Please note that I couldn't verify some of your method calls as I don't have your complete code, so I'm assuming the calls to things like getTimeStamp() and getClassName() will work. You should also do something with the possible IOException that can be thrown when using any of the java.io.* classes - either your function that writes the files should throw this exception (and it be handled elsewhere), or you should do it in the method directly. Also, I assumed that id is of type String - I don't know as your code doesn't explicitly define it. If it is something else like an int, you should probably cast it to a String before using it in the fileName as I have done here.
Also, I replaced your append calls with concat or + as I saw appropriate.
public void writeFile(String value){
String PATH = "/remote/dir/server/";
String directoryName = PATH.concat(this.getClassName());
String fileName = id + getTimeStamp() + ".txt";
File directory = new File(directoryName);
if (! directory.exists()){
directory.mkdir();
// If you require it to make the entire directory path including parents,
// use directory.mkdirs(); here instead.
}
File file = new File(directoryName + "/" + fileName);
try{
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(value);
bw.close();
}
catch (IOException e){
e.printStackTrace();
System.exit(-1);
}
}
You should probably not use bare path names like this if you want to run the code on Microsoft Windows - I'm not sure what it will do with the / in the filenames. For full portability, you should probably use something like File.separator to construct your paths.
Edit: According to a comment by JosefScript below, it's not necessary to test for directory existence. The directory.mkdir() call will return true if it created a directory, and false if it didn't, including the case when the directory already existed.
Trying to make this as short and simple as possible. Creates directory if it doesn't exist, and then returns the desired file:
/** Creates parent directories if necessary. Then returns file */
private static File fileWithDirectoryAssurance(String directory, String filename) {
File dir = new File(directory);
if (!dir.exists()) dir.mkdirs();
return new File(directory + "/" + filename);
}
I would suggest the following for Java8+.
/**
* Creates a File if the file does not exist, or returns a
* reference to the File if it already exists.
*/
public File createOrRetrieve(final String target) throws IOException {
final File answer;
Path path = Paths.get(target);
Path parent = path.getParent();
if(parent != null && Files.notExists(parent)) {
Files.createDirectories(path);
}
if(Files.notExists(path)) {
LOG.info("Target file \"" + target + "\" will be created.");
answer = Files.createFile(path).toFile();
} else {
LOG.info("Target file \"" + target + "\" will be retrieved.");
answer = path.toFile();
}
return answer;
}
Edit: Updated to fix bug as indicated by #Cataclysm and #Marcono1234. Thx guys:)
code:
// Create Directory if not exist then Copy a file.
public static void copyFile_Directory(String origin, String destDir, String destination) throws IOException {
Path FROM = Paths.get(origin);
Path TO = Paths.get(destination);
File directory = new File(String.valueOf(destDir));
if (!directory.exists()) {
directory.mkdir();
}
//overwrite the destination file if it exists, and copy
// the file attributes, including the rwx permissions
CopyOption[] options = new CopyOption[]{
StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES
};
Files.copy(FROM, TO, options);
}
Simple Solution using using java.nio.Path
public static Path createFileWithDir(String directory, String filename) {
File dir = new File(directory);
if (!dir.exists()) dir.mkdirs();
return Paths.get(directory + File.separatorChar + filename);
}
If you create a web based application, the better solution is to check the directory exists or not then create the file if not exist. If exists, recreate again.
private File createFile(String path, String fileName) throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(".").getFile() + path + fileName);
// Lets create the directory
try {
file.getParentFile().mkdir();
} catch (Exception err){
System.out.println("ERROR (Directory Create)" + err.getMessage());
}
// Lets create the file if we have credential
try {
file.createNewFile();
} catch (Exception err){
System.out.println("ERROR (File Create)" + err.getMessage());
}
return file;
}
A simple solution using Java 8
public void init(String multipartLocation) throws IOException {
File storageDirectory = new File(multipartLocation);
if (!storageDirectory.exists()) {
if (!storageDirectory.mkdir()) {
throw new IOException("Error creating directory.");
}
}
}
If you're using Java 8 or above, then Files.createDirectories() method works the best.

Reading/Writing to Properties Files inside the jar file

So i am getting back into writing Java after 4 years so please forgive any "rookie" mistakes.
I need to have a properties file where i can store some simple data for my application. The app data itself won't reside here but i will be storing info such as the file path to the last used data store, other settings, etc.
I managed to connect to the properties file which exists inside the same package as the class file attempting to connect to it and i can read the file but i am having trouble writing back to the file. I am pretty sure that my code works (at least it's not throwing any errors) but the change isn't reflected in the file itself after the app is run in Netbeans.
In the above image you can see the mainProperties.properties file in question and the class attempting to call it (prefManagement.java). So with that in mind here is my code to load the file:
Properties mainFile = new Properties();
try {
mainFile.load(prefManagement.class.getClass().getResourceAsStream("/numberAdditionUI/mainProperties.properties"));
} catch (IOException a) {
System.out.println("Couldn't find/load file!");
}
This works and i can check and confirm the one existing key (defaultXMLPath).
My code to add to this file is:
String confirmKey = "defaultXMLPath2";
String propKey = mainFile.getProperty(confirmKey);
if (propKey == null) {
// Key is not present so enter the key into the properties file
mainFile.setProperty(confirmKey, "testtest");
try{
FileOutputStream fos = new FileOutputStream("mainProperties.properties");
mainFile.store(fos, "testtest3");
fos.flush();
}catch(FileNotFoundException e ){
System.out.println("Couldn't find/load file3!");
}catch(IOException b){
System.out.println("Couldn't find/load file4!");
}
} else {
// Throw error saying key already exists
System.out.println("Key " + confirmKey + " already exists.");
}
As i mentioned above, everything runs without any errors and i can play around with trying to add the existing key and it throws the expected error. But when trying to add a new key/value pair it doesn't show up in the properties file afterwords. Why?
You should not be trying to write to "files" that exist inside of the jar file. Actually, technically, jar files don't hold files but rather they hold "resources", and for practical purposes, they are read-only. If you need to read and write to a properties file, it should be outside of the jar.
Your code writes to a local file mainProperties.properties the properties.
After you run your part of code, there you will find that a file mainProperties.properties has been created locally.
FileOutputStream fos = new FileOutputStream("mainProperties.properties");
Could order not to confuse the two files you specify the local file to another name. e.g. mainAppProp.properties .
Read the complete contents of the resource mainProperties.properties.
Write all the necessary properties to the local file mainAppProp.properties.
FileOutputStream fos = new FileOutputStream("mainAppProp.properties");
switch if file exists to your local file , if not create the file mainAppProp.properties and write all properties to it.
Test if file mainAppProp.properties exists locally.
Read the properties into a new "probs" variable.
Use only this file from now on.
Under no circumstances you can write the properties back into the .jar file.
Test it like
[...]
if (propKey == null) {
// Key is not present so enter the key into the properties file
mainFile.setProperty(confirmKey, "testtest");
[...]
Reader reader = null;
try
{
reader = new FileReader( "mainAppProp.properties" );
Properties prop2 = new Properties();
prop2.load( reader );
prop2.list( System.out );
}
catch ( IOException e )
{
e.printStackTrace();
}
finally
{
if (reader != null) {
reader.close();
}
}
}
[...]
}
output : with prop2.list( System.out );
-- listing properties --
defaultXMLPath2=testtest
content of the file mainAppProp.properties
#testtest3
#Mon Jul 14 14:33:20 BRT 2014
defaultXMLPath2=testtest
Challenge:
Read the Property file location in jar file
Read the Property file
Write the variable as system variables
public static void loadJarCongFile(Class Utilclass )
{
try{
String path= Utilclass.getResource("").getPath();
path=path.substring(6,path.length()-1);
path=path.split("!")[0];
System.out.println(path);
JarFile jarFile = new JarFile(path);
final Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
final JarEntry entry = entries.nextElement();
if (entry.getName().contains(".properties")) {
System.out.println("Jar File Property File: " + entry.getName());
JarEntry fileEntry = jarFile.getJarEntry(entry.getName());
InputStream input = jarFile.getInputStream(fileEntry);
setSystemvariable(input);
InputStreamReader isr = new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null) {
System.out.println("Jar file"+line);
}
reader.close();
}
}
}
catch (Exception e)
{
System.out.println("Jar file reading Error");
}
}
public static void setSystemvariable(InputStream input)
{
Properties tmp1 = new Properties();
try {
tmp1.load(input);
for (Object element : tmp1.keySet()) {
System.setProperty(element.toString().trim(),
tmp1.getProperty(element.toString().trim()).trim());
}
} catch (IOException e) {
System.out.println("setSystemvariable method failure");
}
}

Properties setting via Servlet

I want to set data from configures.properties via servlet. configures.properties is locating in WEB-INF/classes. This is how I'm getting data:
public static String getDbPassword() {
Properties prop = new Properties();
try {
// load a properties file
InputStream in = Configures.class.getResourceAsStream(INPUT_FILE);
prop.load(in);
// get the property value
return prop.getProperty("dbPassword");
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
But how to set? This is how I did:
public static void setDbPassword(String str) {
Properties prop = new Properties();
try {
//load a properties file
InputStream in = Configures.class.getResourceAsStream(INPUT_FILE);
prop.load(in);
prop.setProperty("dbPassword", str);
prop.store(new FileOutputStream(INPUT_FILE), null);
} catch (IOException ex) {
ex.printStackTrace();
}
}
But I'm catching java.io.FileNotFoundException after this. I think it happens after prop.store(new FileOutputStream(INPUT_FILE), null);. How should I modify OutputStream?
UPD:
This is how INPUT_FILE looks:
private static final String INPUT_FILE = "/config.properties";
Your INPUT_FILE is a resource path which getResourceAsStream will resolve relative to the classpath, but you're then trying to pass the same string to the FileOutputStream constructor which will try and treat it as an absolute path relative to the root of the filesystem. These are two different locations.
You could use ServletContext.getRealPath("WEB-INF/classes" + INPUT_FILE) to get the path you need for the FileOutputStream.
But the higher level issue here is that you shouldn't assume that your web application will have write access to its WEB-INF, or even that the directory exists on disk at all (e.g. if the app is running directly from a WAR rather than a directory unpacked on disk). If you want to store configuration data that can change then it should go in a file at a known location outside the web app (the location of this file could be an init parameter) where you know you will have read and write permission. This also stops your changes being overwritten when you deploy a new version of the app.
URL url = Configures.class.getResource(INPUT_FILE);
File file = new File(url.toURI());
OutputStream outputStream = new FileOutputStream(file);
...
prop.store(outputStream, null);
Try a FileWriter instead:
Writer writer = new FileWriter(INPUT_FILE);
...
prop.store(writer, null);
Can you try the following:
While reading the file
URL url = classLoader.getResource(INPUT_FILE);
InputStream in = url.openStream();
While writing :
new FileOutputStream(url.toURI().getPath())
Any files in your webapp should be considered read only. If you want mutable data you should use a database or some other data store.
J2EE advises against manipulating local files as it raises issues of clustering, transactions and security among other things.

How to read from a file not in Eclipse in Java

I have a file which is needed for running tests - this file needs to be personalized (name and password) by whomever is running the test. I do not want to store this file in Eclipse (since it would need to be changed by whomever runs the test; also it would be storing personal info in the repo), so I have it in my home folder (/home/conrad/ssl.properties). How can I point my program to this file?
I've tried:
InputStream sslConfigStream = MyClass.class
.getClassLoader()
.getResourceAsStream("/home/" + name + "/ssl.properties");
I've also tried:
MyClass.class.getClassLoader();
InputStream sslConfigStream = ClassLoader
.getSystemResourceAsStream("/home/" + name + "/ssl.properties");
Both of these give me a RuntimeException because the sslConfigStream is null. Any help is appreciated!
Use a FileInputStream to read data from a file. The constructor takes a string path (or a File object, which encapsulates string path).
Note 1: A "resource" is a file which is in the classpath (alongside your java/class files). Since you don't want to store your file as a resource because you don't want it in your repo, ClassLoader.getSystemResourceAsStream() is not what you want.
Note 2: You should use a cross-platform way of getting a file in a home directory, as follows:
File homeDir = new File(System.getProperty("user.home"));
File propertiesFile = new File(homeDir, "ssl.properties");
InputStream sslConfigStream = new FileInputStream("/home/" + name + "/ssl.properties")
You can simplify your work, using Java's 7 method:
public static void main(String[] args) {
String fileName = "/path/to/your/file/ssl.properties";
try {
List<String> lines = Files.readAllLines(Paths.get(fileName),
Charset.defaultCharset());
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
You can also improve your way of reading properties file, using Properties class and forget about reading and parsing your .properties file:
http://www.mkyong.com/java/java-properties-file-examples/
Is this a graphics program (ie. using the Swing library)? If so it is a pretty simple task of using a JFileChooser.
http://docs.oracle.com/javase/6/docs/api/javax/swing/JFileChooser.html
JFileChooser f = new JFileChooser();
int rval = f.showOpenDialog(this);
if (rval == JFileChooser.APPROVE_OPTION) {
// Do something with file called f
}
You can also use Scanner to read the file.
String fileContent = "";
try {
Scanner scan = new Scanner(
new File( System.getProperty("user.home")+"/ssl.properties" ));
while(scan.hasNextLine()) {
fileContent += scan.nextLine();
}
scan.close();
} catch(FileNotFoundException e) {
}

i want relative path for a file in java

I am new to java. I want to read a properties file in java. But i have my properties file in a different path in the same project.
I don't want to hard-code it. I want try with dynamic path.
Here is my code,
Properties properties = new Properties();
try{
File file = new File("myFile.properties");
FileInputStream fileInput = new FileInputStream(file);
properties.load(fileInput);
}catch(Exception ex)
{
System.err.println(ex.getMessage());
}
my file is in the folder, webapp/txt/myFile.properties.
Can any one help me in solving this issue?.
One way to solve this is split the absolute path to you file in two parts
Path till your project folder
path from you project folder onwards (Relative path)
You can tread these two properties in your application and concatenate and get the absolute path of the file. The relative path remains configurable.
public Properties loadDBProperties() {
InputStream dbPropInputStream = null;
dbPropInputStream = DbConnection.class
.getResourceAsStream("MyFile.properties");
dbProperties = new Properties();
try {
dbProperties.load(dbPropInputStream);
} catch (IOException ex) {
ex.printStackTrace();
}
return dbProperties;
}
you can call this method from
dbProperties = loadDBProperties();
String dbName = dbProperties.getProperty("db.schema");//you can read your line form here of properties file
if its under webapp/txt.myFile.properties and webapp is the public web space, then you need to read it using absolute URL
getServletContext().getRealpath("/txt/myFile.properties")
Properties prop=new Properties();
InputStream input = getServletContext().getResourceAsStream("/txt/myFile.properties");
prop.load(input);
System.out.println(prop.getProperty(<PROPERTY>));

Categories