Unable to write in file in runnable JAR file [duplicate] - java

This question already has answers here:
How can an app use files inside the JAR for read and write?
(5 answers)
Java - Writing to txt in a JAR file [duplicate]
(3 answers)
Closed 8 months ago.
I saved the runnable JAR file to another directory (not in the project folder). Now, I can read data from the runnable JAR file, but I can't write any data in file.
Code for reading data:
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getClassLoader()
.getResourceAsStream("TaskList.txt")));
StringBuilder sb = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null) {
sb.append(line + "\n");
textArea.setText(sb.toString());
}
reader.close();
}
catch(Exception ex) {
JOptionPane.showMessageDialog(null, "File Not Found");
}
Code for writing data:
try{
String content = textArea.getText();
Writer writer = new OutputStreamWriter(new FileOutputStream("bin/TaskList.txt"));
writer.write(content);
writer.close();
}
catch(Exception ex) {
}

Once you have compiled a JAR, the files within cannot be changed. A similar question to this has been asked and answered here.
An explanation for why you cannot do this is, a JAR is similar to a ZIP file. In order to change something inside it must be unzipped, edited, then rezipped. This is the same for archive files like rar or 7z. If you need to write to a file, the file must be local, and can't be within the archived JAR.

Related

Null pointer when reading a Properties file from another folder [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
My application will check if a Properties file exists and create one if not.
try{
// create new file
String path="c:\\temp\\LaserController.properties";
File file = new File(path);
String comport = "Comport=COM1";
String Parity = "parity=none";
String baud = "baud=9600";
String Stopbits = "StopBits=0";
String databits = "DataBits=8";
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
// write in file
bw.write(comport);
bw.newLine();
bw.write(Parity);
bw.newLine();
bw.write(baud);
bw.newLine();
bw.write(Stopbits);
bw.newLine();
bw.write(databits);
// close connection
bw.close();
}
But when i try to read the properties file like this i get a Null pointer.
else {
Properties prop = new Properties();
InputStream input = LaserControllerUI.class.getResourceAsStream("c:\\temp\\LaserController.properties");
// load a properties file
prop.load(input);
// get the property value and print it out
System.out.println(prop.getProperty(Comport+"comport"));
System.out.println(prop.getProperty("Parity"));
System.out.println(prop.getProperty("Baud"));
input.close();
}
}catch(Exception e){
System.out.println(e);
}
}
It fails on the InputStream input line but i dont know why. the file exists and my application can access it because it put it there in the first place. What am i doing wrong?
The file has to be in a location that is accessible to users to change parameters.
getResourceAsStream method needs a "class-path relative" name. You are providing an absolute path. Try to use FileInputStream instead.
E.g:
InputStream input = new FileInputStream("c:\\temp\\LaserController.properties");
I suggest using Properties.save() to ensure it is written in a format when can be read.
I suggest you look at the text file to see what was written.
BTW The properties are case sensitive. you write
Comport
parity
baud
but you read
Comport+"comport"
Parity
Baud
so they will all be null.
Move that file to resource folder or add that folder as resource folder
getClass().getClassLoader().getResourceAsStream("LaserController.properties")

How can I modify a text file inside a Jar file while runtime? [duplicate]

This question already has answers here:
Modifying a file inside a jar
(14 answers)
Closed 7 years ago.
Well as the question says, How is that possible?
This file is my proyect structure (I'm using eclipse).
When exported as Jar, I can access and print the "root.ini" content through console with the code below but, How can I write to that file while runtime?
This method is called from 'Main.java'
private void readRoot(){
InputStream is = getClass().getResourceAsStream("/img/root.ini");
BufferedReader br = null;
br = new BufferedReader(new InputStreamReader(is));
String path = "";
try {
path = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(path);
}
What I'm actually trying to do is get some text from a JTextField, and save it to "root.ini" file.
So when I try to write to that file like this
private void writeRoot() {
URL u = getClass().getResource("/img/root.ini");
File f = null;
try {
f = new File(u.toURI());
FileWriter fw = new FileWriter(f.getAbsolutePath());
BufferedWriter bw = new BufferedWriter(fw);
bw.write("Sample text"); //This String is obtained from a TextField.getText();
bw.close();
fw.close();
} catch (URISyntaxException | IOException e) {
e.printStackTrace();
}
}
And throws me this error
C:\Users\Francisco\Desktop\tds>java -jar TDS.jar
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.(Unknown Source)
at main.Configuracion.writeRoot(Configuracion.java:99)
at main.Configuracion.access$1(Configuracion.java:95)
You can't change any content of a jar which is currently used by a jvm. This file is considered locked by the operating system and therefore can't be changed.
I suggest to write this file outside your jar file. e.g. in a /conf directory relative to the current working dir.

AndroidStudio can't find CSV file. Tried Absolute File Path & Relative File Path

I've created a simple Android app that displays text to the user.
Now I'm attempting to implement a CSVReader to retrieve text from a CSV file. After hours of trying different things.
I finally implemented an open source CSVReader (At least it's not giving me any compile errors anymore).
Now when I run the app, it crashes and I get a "file not found" exception. Either I'm not placing my CSV file in the correct location, I'm not referencing the correct file path, or both.
I've tried using the absolute file path (ex. starting with my C:/Users/Tim/AndroidStudioProjects/...).
I've also tried using a relative path starting with the Assets folder (ex. "Assets/SOCIAL_POSTS.csv") and nothing I've tried has worked.
I've tried looking for similar Questions on Stack Overflow, and I've tried several variations of file paths and nothing has worked so far. What do you think I should try next?
Here is a link to this project on GitHub.
The code pointing to the CSV file is under
app > src > main > java > com > example > tim > inspiredquestions
The CSV file is called SOCIAL_POSTS.csv and it is under
Assets > SOCIAL_POSTS.csv
Final note: I've used StackOverflow for debugging help for a year now, but this is the first question I've asked.
Thank-you for your patience! I'm trying to be as self-reliant as I can, but I'm going on a limb and asking for help. I'm sure this problem has a simple answer I'm overlooking.
I finally figured out the answer. I added
final CSVReader csvReader = new CSVReader(new InputStreamReader(c.getAssets().open("SOCIAL_POSTS.csv") to my load function in Game.java after looking at the answer to this question. Previously I had put my CSV file in an assets folder under app/src/main but I didn't know how to access the file properly until reviewing that SO post.
How I use Android Studio for files is to position my files in the raw folder, then push them to the /data/data/yourapplication/files directory. I do this through Tools/Android/Android Device Monitor and navigate to the /data/data/yourapplication/files directory and select an icon in the upper right that says "Push a file onto the device", then navigate to the raw files in my app and select the csv file(s) I want placed in the /files directory.
From that point I aim my stream readers at that directory,
in my case, /data/data/app/com.android/example/darrell/MenuPlanner/files Directory. Files addressed here use the file extension and do not need the path specified:
public List<EntreeData> ReadEntreesFromFilesDir(Context inContext) {
this.mContext = inContext;
List<String> lines = new ArrayList<String>();
String[] separated;
try {
FileInputStream fis = mContext.openFileInput("entrees.csv");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader bufferedReader = new BufferedReader(isr);
while ((mLine = bufferedReader.readLine()) != null) {
if (mLine == null) break;
lines.add(mLine);
}
fis.close();
isr.close();
} catch (FileNotFoundException e) {
Log.d("FILE ERROR", e.getMessage() + " not found");
} catch (IOException ioe) {
Log.d("FILE ERROR", ioe.getMessage());
}
for (int x = 0;x<lines.size();x++){
separated = lines.get(x).split(",");
EntreeData thisEntree = new EntreeData();
thisEntree.setEntreeName(separated[0].trim());
thisEntree.setCategory(separated[1].trim());
thisEntree.setSubcategory(separated[2].trim());
thisEntree.setRecipe(separated[3].trim());
mEntreeList.add(thisEntree);
}
return mEntreeList;
}
As a fallback I read from /res/raw directory which is not writeable and I am assured of file integrety. Files here do not use an extension, so point your stream reader at a file without using the extension name.
Also use the asset manager to access these files:
public List<EntreeData> ReadEntreesFileFromRaw(Context inContext) {
this.mContext = inContext;
List<String> lines = new ArrayList<String>();
String[] separated;
AssetManager assetManager = mContext.getAssets();
try {
InputStream inputStream = mContext.getResources().openRawResource(R.raw.entrees);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
int lineCount = 0;
while ((mLine = reader.readLine()) != null) {
separated = mLine.split(",");
EntreeData entreeEntry = new EntreeData();
if (mLine == null) break;
separated = mLine.split(",");
entreeEntry.setEntreeName(separated[0].trim());
entreeEntry.setCategory(separated[1].trim());
entreeEntry.setSubcategory(separated[2].trim());
entreeEntry.setRecipe(separated[3].trim());
mEntreeList.add(lineCount, entreeEntry);
lineCount++;
}
inputStream.close();
} catch (FileNotFoundException e) {
Log.d("FILE ERROR", e.getMessage() + " not found");
} catch (IOException ioe) {
Log.d("FILE ERROR", ioe.getMessage());
}
return mEntreeList;
}
Good luck and happy programming!

Reading a text file in a .jar-application [duplicate]

This question already has answers here:
getResourceAsStream returns null
(26 answers)
Closed 8 years ago.
With this code I want a .jar-file to read the text-file "file.txt" which is located in the jar in folder data. This is a application is programmed with Processing, so all files I want to read are in the data folder. Can anybody explain why I get a NullPointerException? The file exists and contains text.
import java.io.*;
void setup() {
size(500, 500);
try {
// HERE I TRY TO READ THE FILE WHICH IS LOCATED IN THE JAR FILE IN THE FOLDER "DATA"
InputStream is = getClass().getResourceAsStream("/data/file.txt");
// HERE I GET A NULL-POINTER-EXCEPTION BECAUSE THE FILE CANNOT BE READ (IS = NULL, WHY IS THE INPUT STREAM NULL?)
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// THE FIRST LINE OF THE DOCUMENT IS READ AND PRINTED IN THE CONSOLE
String read = br.readLine();
br.close();
println(read);
}
catch (IOException e) {
// IF THE FILE DOESN'T EXIST AN IO-EXCEPTION WILL BE CAUGHT
println("Error reading file");
}
}
getClass().getResourceAsStream("/data/file.txt"); returns null, because it uses that class' system loader which can't see your jar. Use instead
YourClassName.class.getResourceAsStream("/data/file.txt");

Reading a text file in war archive [duplicate]

This question already has answers here:
Where to place and how to read configuration resource files in servlet based application?
(6 answers)
Closed 5 years ago.
I am trying to read a text file from my war archive and display the contents in a facelets page at runtime. My folder structure is as follows
+war archive > +resources > +email > +file.txt
I try to read the file in the resources/email/file.txt folder using the following code
File file = new File("/resources/email/file.txt");
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
StringBuffer buffer = new StringBuffer();
if (reader != null) {
String line = reader.readLine();
while (line != null) {
buffer.append(line);
line = reader.readLine();
// other lines of code
The problem however is that when I the method with the above code runs, A FileNotFoundException is thrown. I have also tried using the following line of code to get the file, but has not been successful
File file = new File(FacesContext.getCurrentInstance()
.getExternalContext().getRequestContextPath() + "/resources/email/file.txt");
I still get the FileNotFoundException. How is this caused and how can I solve it?
Try below:
InputStream inputStream =
getClass().getClassLoader().getResourceAsStream("/resources/email/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream ));
Try to avoid the File, as this is for reading things from the file system.
As your resource is bundled into the WAR, you can access it via the classloader.
Ensure that the resource is bundled into your WEB-INF/classes folder.
InputStream in =
new InputStreamReader(FileLoader.class.getClassLoader().getResourceAsStream("/resources/email/file.txt") );
This is a good blog on the topic
http://haveacafe.wordpress.com/2008/10/19/how-to-read-a-file-from-jar-and-war-files-java-and-webapp-archive/
If you want to get the java File object, you can try this:
String path = Thread.currentThread().getContextClassLoader().getResource("language/file.xml").getPath();
File f = new File(path);
System.out.println(f.getAbsolutePath());
I prefer this approach:
InputStream inputStream = getClass().getResourceAsStream("/resources/email/file.txt");
if (inputStream != null) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
...
} catch ...
} else ...
Three reasons:
it supports both: loading resources from an absolute path and from a relative path (starting from the given class) -- see also this answer
the way to obtain the stream is one step shorter
it utilizes the try-with-resources statement to implicitly close the underlying input stream

Categories

Resources