How to read / write in a file embedded in a jar [duplicate] - java

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");
}
}

Related

Eclipse: Can't add a relative path to a .txt file to a Java application

I have a Java web application (running on Tomcat 9.0 on Linux) that retrieves a message (including a unique 4-letter location code), looks up the code in a CSV file and returns a human-readable location name. For example CLLK,Clear Lake.
The application was working well, when I'd loaded the file's absolute path /home/beau/eclipse-workspace/pagerfeed/brigades.csv.
But when I tried to change this to a relative path pagerfeed/brigades.csv, the file couldn't be found. Further investigation found that Eclipse was expecting to find the file at /home/beau/pagerfeed/brigades.csv, completely ignoring my eclipse-workspace folder.
Does anyone know what might be causing this?
Additionally, the file is currently just in the project's root directory, which I assume isn't best practice. Considering it will be deployed as a WAR file, is there somewhere better to put this file? (It can be accessible from the address bar.)
The code to load the file (yes it's messy - the commented lines are other methods I've tried that haven't worked properly):
// The code that actually gets the file (not working)
Brigade.importBrigadesFromFile("pagerfeed/brigades.csv");
// The code, when it WAS working
Brigade.importBrigadesFromFile("/home/beau/eclipse-workspace/pagerfeed/brigades.csv");
// And my background code to read the file
public Iterable<CSVRecord> read(String file) {
Iterable<CSVRecord> records = null;
try {
Reader reader = new FileReader(file);
// InputStream inputStream = getClass().getClassLoader().getResourceAsStream(file);
// InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(file);
// BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
records = CSVFormat.DEFAULT.parse(reader);
System.out.println("Found the CSV file!");
} catch (FileNotFoundException fe) {
String absolutePath = new File("/data/testFile").getAbsolutePath();
System.out.println("File was not found.");
System.out.println("Try putting file here: " + absolutePath + ". ");
fe.printStackTrace();
} catch (IOException ioe) {
System.out.println("Unable to parse the CSV file. Details: ");
ioe.printStackTrace();
} catch (NullPointerException ne) {
System.out.println("Could not read file at " + new File("filegoeshere").getAbsolutePath());
System.out.println("InputStream returned null. Details: ");
ne.printStackTrace();
}
return records;
}
Screenshot of my Eclipse path variables: https://imgur.com/a/Gnqrj

File is not readable after file.setReadable(true)

I try to read the file and get FileNotFoundExeption.
File file = new File("News.out");
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
try{
in.readObject();
}
I check, that the file really exists in the directory and check "readable" property of the file.
Then I added programmatical setting of "readable" and "writable" properties
file.setReadable(true);
file.setWritable(true);
System.out.println(file.canRead());
System.out.println(file.canWrite());
And got in logs false, false.
What may be the reason of this?
EDIT:
I tried JSR 203 and use this code:
Path path = FileSystems.getDefault().getPath(filename);
try(
final InputStream in = Files.newInputStream(path);
) {
ObjectInputStream objectInputStream = new ObjectInputStream(in);
newsStorage.setEntities((ArrayList<News>) objectInputStream.readObject());
} catch (NoSuchFileException e) {
createFile(path, filename);
handleException(e);
}
And createFile() method:
private void createFile(Path path, String string) {
try {
Files.newOutputStream(path, StandardOpenOption.CREATE);
} catch (IOException e1) {
e1.printStackTrace();
}
}
File was not created.
Do I understand correctly, that
Files.newOutputStream(path, StandardOpenOption.CREATE);
should create a file?
Do yourself a favor and drop File. Use JSR 203 instead.
Try and use:
try (
final InputStream in = Files.newInputStream("News.out");
) {
// work with "in" here
}
If you can't perform the opening then you will at least have an exception telling you what exactly is wrong, something File has never been able to do.
After that, if you want to set permissions on the file, you can also do so with JSR 203 but that depends on the capabilities of the underlying filesystem. If your filesystem is POSIX compatible then you may use this method for instance. But it also may be that you cannot modify the permissions of the file either.

Can't write my arrayList to a file as expected

I have this method, supposed to write an arrayList to a file:
private ArrayList<String> readFromFile() {
String ret = "";
ArrayList<String> list = new ArrayList<String>();
try {
InputStream inputStream = openFileInput("jokesBody.bjk");
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(
inputStream);
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
String receiveString = "";
StringBuilder stringBuilder = new StringBuilder();
while ((receiveString = bufferedReader.readLine()) != null) {
list.add(receiveString);
}
inputStream.close();
ret = stringBuilder.toString();
System.out.println("DA CRAZY FILE: " + ret);
}
} catch (FileNotFoundException e) {
Log.e("login activity", "File not found: " + e.toString());
} catch (IOException e) {
Log.e("login activity", "Can not read file: " + e.toString());
}
return list;
}
The problem with it is that it writes the values like [item1, item2, item3] and later when I need to load a the values back to a listArray it's loading the whole line at index 0. Now I have found the corerct way to write and read the arrayList, but I'm having troubles accessing teh file.
Here is the code I tried:
private void writeToFile(ArrayList<String> list) {
try {
FileOutputStream fos = new FileOutputStream("jokesBody.bjk");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(list); // write MenuArray to ObjectOutputStream
oos.close();
} catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
But it throws the following exception:
02-12 09:21:10.227: E/Exception(2445): File write failed: java.io.FileNotFoundException: /jokesBody.bjk: open failed: EROFS (Read-only file system)
Where is the mistake, where is the default app file location? I know that I'm missing something small, but as an android beginner, I'm not able to spot it.
Isn't this:
java.io.FileNotFoundException: /jokesBody.bjk: open failed: EROFS (Read-only file system)
the issue ? You're writing to a non-writeable area. Change where you're writing to (perhaps creating a temporary file would be a simple first step - I'm not familiar with Android but I assume this is possible)
Your file seems to be read only. You cannot write to a read only file!!!
I don't think you're actually saving the file where you think you are. Look at this tutorial on writing a file to external storage. A few things:
(1) You need to request permission in your manifest to write to external storage. If not you will end up with a read only situation.
(2) You need to get the external storage directory in your code before you write to it. This should be preceeded with a general check as to whether your file directory is writeable in the first place:
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
You can then create a specific directory for the files you want to store and store them in that location so you can find them later. For example:
public File getAlbumStorageDir(String albumName) {
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
You can then write content to the file that is returned
When you are developing for Android, you must get the OutputStream from the Context:
fos = context.openFileOutput("jokesBody.bjk", Context.MODE_PRIVATE);
An explanation about how to work with files on Android is here: Saving Files

Why AccessDeniedException is raising when using just created folder?

I'm creating simple object serialization, and creation of BufferedOutputStream is raising an exception AccessDeniedException. Here is the code:
Path filePath = Paths.get("c:\\temp\\");
File xmlFile = new File("c:\\temp\\");
boolean success = xmlFile.mkdirs();
if (!success && ! xmlFile.exists() ) {
// Directory creation failed
System.out.println("Failed to create a file: " + filePath);
}
try (
ObjectOutputStream objectOut = new ObjectOutputStream(
new BufferedOutputStream(Files.newOutputStream(filePath, StandardOpenOption.WRITE)))){
// Write three objects to the fi le
objectOut.writeObject(solarSystem); // Write object
System.out.println("Serialized: " + solarSystem);
} catch(IOException e) {
e.printStackTrace();
}
But directory is empty and if it doesn't not exist, it's created...
I'll repeat my comment here: you seem to try to write to a directory not to a file. Try changing filePath to a file instead.

Problem in Zipping a File

When I run my code and use the files that are in the resource folder of my project itself, I face no problems. It zips the file successfully and I can extract it using WINZIP. The problem comes when I try to zip a file that is not in the project folder.
When I do the same, I am passing the Absolute Path of both the src and the dest files. My program doesn't give any exceptions, but when I try to open that zip file, I get an error saying, File is Invalid.
Can anyone tell me why this may be happening.
public static void compress(String srcPath, String destPath) {
srcFile = new File(srcPath);
destFile = new File(destPath);
try {
fileInputStream = new FileInputStream(srcFile);
fileOutputStream = new FileOutputStream(destFile);
zipEntry = new ZipEntry(srcPath);
zipOutputStream = new ZipOutputStream(fileOutputStream);
zipOutputStream.putNextEntry(zipEntry);
byte[] data = new byte[12];
while ((fileInputStream.read(data)) != -1) {
zipOutputStream.write(data);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
fileInputStream.close();
zipOutputStream.close();}catch (Exception e) {
e.printStackTrace();
}
}
}
You should not store paths with drive letters in your zip file because when you try to extract your zip, it will try to create a directory with the name of the drive and fail.
You will need to change your code so that it removes the drive letter from the path before creating the ZipEntry.

Categories

Resources