Nested try-catch IOException inside catch for FileNotFoundException - java

I feel like nesting try-catch logic inside a catch block is not ideal / not clean code, but I am not sure how to refactor my code such that:
When there is no file found (catch FileNotFoundExeption) my program will create a new file (which generates IOException), without nesting the try catch.
public String hiMessage() {
String message = "Hello! Initializing program.\n";
try {
storage.readFromTasksFileToList(tasks);
message += "This is where you left off previously:\n";
} catch (FileNotFoundException e) {
message += "Fetching failed. " + e.getMessage() + "\n";
message += "Creating file now...\n";
File dukeTxt = new File(Duke.filePath);
try { // nested try catch inside catch
dukeTxt.createNewFile(); // throws IOException
message += "File created! " + dukeTxt.getAbsolutePath() + "\n";
message += "Reading file...\n";
} catch (IOException ioe) {
message += "\t File creation was not successful. \n";
message += "\t Exiting system.";
return message;
}
}
message += getAllTasksAsString();
return message;
}

Ideally, you should check the existance of the file before reading it. Something along these lines:
File dukeTxt = new File(Duke.filePath);
if (dukeTxt.exist()) {
try { dukeTxt.createNewFile(); }
catch(IOException ioe) {...}
}
try { storage.readFromTasksFileToList(tasks); }
catch (FileNotFoundException fnfe) {...}

Related

Zip4j no error, extract all failed even though a error should appear

I use zip4j to unzip zip packages which are safed by a password (AES-256). My problem is not, that the code is not working, rather that it doen't throw any error when the password doesn't match with the actual on the .zip.
the .zip has a password with 123 and for zip4j I set the password 123456789. So he is not able to extract all. I expect an Error or any message, that it could not extract. The actual case is, he doesn't extract it but no exception or error message, nothing.
Any Idea how I can check if the extraction was successful?
protected void unpackZip(String destinationPath, String archivePath) throws InterruptedException {
int onChange = 0;
try {
ZipFile zipFile = new ZipFile( archivePath );
zipFile.setRunInThread( true );
if (zipFile.isEncrypted()) {
zipFile.setPassword( "123456789");
}
zipFile.extractAll( destinationPath );
// http://www.lingala.net/zip4j/forum/index.php?topic=68.0
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
while (progressMonitor.getState() == ProgressMonitor.STATE_BUSY) {
// To get the percentage done
if (onChange != progressMonitor.getPercentDone()) {
onChange = progressMonitor.getPercentDone();
sendWebStatusUiMessage( "Extracted : " + onChange + "% ", "update" );
}
try {
Thread.sleep( 1000 );
} catch (Exception e) {
}
}
} catch (ZipException e) {
e.printStackTrace();
}
}
This answer is a bit late, but just in case it might be useful for anyone:
When running zip4j in thread mode, you have to check for the status of the task execution and exception (if errored), after the while loop.
while (progressMonitor.getState() == ProgressMonitor.STATE_BUSY) {
// To get the percentage done
if (onChange != progressMonitor.getPercentDone()) {
onChange = progressMonitor.getPercentDone();
sendWebStatusUiMessage( "Extracted : " + onChange + "% ", "update" );
}
try {
Thread.sleep( 1000 );
} catch (Exception e) {
}
}
if (progressMonitor.getResult().equals(ProgressMonitor.Result.SUCCESS)) {
System.out.println("Successfully added folder to zip");
} else if (progressMonitor.getResult().equals(ProgressMonitor.Result.ERROR)) {
System.out.println("Error occurred. Error message: " + progressMonitor.getException().getMessage());
} else if (progressMonitor.getResult().equals(ProgressMonitor.Result.CANCELLED)) {
System.out.println("Task cancelled");
}

Android internal Storage error

I am really new to android and writing a simple game for android.
In the game, like in most games you have score,
now, I want the score to be saved in Internal Storage, and for some reason, I manage to save the score, but not load it back.
here is the code:
final TextView best = (TextView) findViewById(R.id.best);
public int read = -1;
public StringBuffer buffer = new StringBuffer();
public String scoreTxt = buffer.substring(0, buffer.indexOf(" ") + 1);
public int score = 0;
// Save
try {
fileOutputStream = openFileOutput("record.txt", Context.MODE_PRIVATE);
fileOutputStream.write(scoreString.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Toast.makeText(MainActivity.this, "Save() works fine", Toast.LENGTH_SHORT).show();
// load
try {
FileInputStream fileInputStream = openFileInput("record.txt");
while ((read = fileInputStream.read())!= -1){
buffer.append((char)read);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
best.setText("Best: " + scoreTxt);
Toast.makeText(MainActivity.this, "load() is good too " + scoreTxt, Toast.LENGTH_SHORT).show();
when I run the app, there is no crash or anything special in the logcat, but when ever I use scoreTxt the output is nothing, just " ".
can somebody help me solve this problem? Thanks
You never assign scoreTxt a value in your code.
You need to parse buffer after it has being populated.Now when scoreTxt is initialized buffer is null
You need to replace this
best.setText("Best: " + scoreTxt);
with
scoreTxt = buffer.substring(0, buffer.indexOf(" ") + 1);
best.setText("Best: " + scoreTxt);
In addition I wouldn't store game score into a file because score changes frequently and you want to avoid disk access a lot. Store it in SharedPreferences and from time to time flush it to a file on a background thread.

Why does my program stop running and does not return error?

I put the declaration in the while loop, and the program would not running and also does not return any error. I suspect the while loop become an infinite loop.
try
{
while (true)
{
inputStream = new ObjectInputStream (new FileInputStream (fileName));
Ship copyObject = (Ship) inputStream.readObject();
String nameCompany = copyObject.getCompanyName();
if (compName.equalsIgnoreCase(nameCompany)){
listShipName += (copyObject.getShipName() + ", ");
numberOfShip ++;
}
}
}
catch (EOFException e)
{
}
catch (Exception e)
{
e.printStackTrace();
}
But if I put the declaration of input stream out of the while loop, the program runs successfully. Can someone explain why this happens?
try
{
inputStream = new ObjectInputStream (new FileInputStream (fileName));
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
while (true)
{
Ship copyObject = (Ship) inputStream.readObject();
String nameCompany = copyObject.getCompanyName();
if (compName.equalsIgnoreCase(nameCompany)){
listShipName += (copyObject.getShipName() + ", ");
numberOfShip ++;
}
}
}
catch (EOFException e)
{
}
catch (Exception e)
{
e.printStackTrace();
}
You're reopening your file on every iteration through the loop, which means you are only ever reading the first object from the file. But you're reading the same object over and over again.
As well as opening your file only once, you really should try to detect the end of file without throwing an exception. As a matter of style, exceptions should be thrown when things go wrong, not as a matter of course.
Now I realize that in each iteration, I reopen the input stream, so the loop would not reach to the end of the file, and it becomes infinite.

How do I get matcher.find while loop to write to text file? java [duplicate]

This question already has an answer here:
Writing to a file but only last line saved
(1 answer)
Closed 9 years ago.
I'm using a while(matcher.find()) loop to write certain substrings to a file. I get a list of the matched strings occurring in the file in my System.out console just fine, but when I try to use FileWriter to write to a text file, I only get the very last string in the loop written. I've scoured stackoverflow for similar problems (and it lives up to its name), I couldn't find anything that helped me. And just to clarify this isn't being run on the EDT. Can anyone explain where to look for the problem?
try {
String writeThis = inputId1 + count + inputId2 + link + inputId3;
newerFile = new FileWriter(writePath);
//this is only writing the last line from the while(matched.find()) loop
newerFile.write(writeThis);
newerFile.close();
//it prints to console just fine! Why won't it print to a file?
System.out.println(count + " " + show + " " + link);
} catch (IOException e) {
Logger.getLogger(Frame1.class.getName()).log(Level.SEVERE, null, e);
} finally {
try {
newerFile.close();
} catch (IOException e) {
Logger.getLogger(Frame1.class.getName()).log(Level.SEVERE, null, e);
}
}
}
Quick fix:
change
newerFile = new FileWriter(writePath);
to
newerFile = new FileWriter(writePath, true);
This uses the FileWriter(String fileName, boolean append) constructor.
Better fix:
create the FileWriter outside of the while(matcher.find()) loop and close it afterwards (or use it as a try with resources initilzation).
the code would be something like:
try (FileWriter newerFile = new FileWriter(writePath)) {
while (matcher.find()) {
newerFile.write(matcher.group());
}
} ...
You should not create an instance of FileWriter every loop iteration. You need to leave the usage of method write() there and init FileWriter before loop and close it after loop.
Please check as follows:
FileWriter newerFile = new FileWriter(writePath);
while(matcher.find())
{
xxxxx
try {
String writeThis = inputId1 + count + inputId2 + link + inputId3;
//this is only writing the last line from the while(matched.find()) loop
newerFile.write(writeThis);
newerFile.flush();
//it prints to console just fine! Why won't it print to a file?
System.out.println(count + " " + show + " " + link);
} catch (IOException e) {
Logger.getLogger(Frame1.class.getName()).log(Level.SEVERE, null, e);
} finally {
try {
newerFile.close();
} catch (IOException e) {
Logger.getLogger(Frame1.class.getName()).log(Level.SEVERE, null, e);
}
}
}
}

Cannot read file just written to

I am trying to read from a file to which some user credentials were written. I want to write the file to an internal storage location. The code:
private void writeSendDetails(String name, String number, String emailID) {
//This function writes details to userCredentials.txt and also sends it to server.
String text = "Name: " + userName + "\n" + "Number: " + userNumber + "\n" + "Email ID:" + userEmailID;
FileOutputStream fos = null;
try {
fos = openFileOutput(userCredFile, MODE_PRIVATE);
Log.v(this.toString(), fos.toString());
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(fos != null) {
OutputStreamWriter osw = new OutputStreamWriter(fos);
try {
osw.write(text);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.v(this.toString(), "IOException caught in osw.write");
e.printStackTrace();
}
try {
osw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
osw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Log.v(this.toString(), "Written everything to userCredentials.txt");
readUserCredentials();
//code to send to server should begin here.
}
private void readUserCredentials() {
//function to read name, number and email ID from userCredentials.txt
/* Steps:
* 1. Check if file exists.
* 2. If it does, read all relevant credentials.
*/
File f = new File(userCredFile);
if(f.canRead()) {
Log.v(this.toString(), "Can open userCredentials for reading from.");
}
try {
FileReader fis = new FileReader(f);
Log.v(this.toString(), "Wrapping a buffered reader around file reader.");
BufferedReader bufRead = new BufferedReader(fis, 100);
String line;
try {
while((line = bufRead.readLine()) != null) {
Log.v(this.toString(), "Line read = " + line);
line = bufRead.readLine();
if(line.indexOf("Name: ") != -1) {
Log.v(this.toString(), "Found name in the string.");
userName = line.substring(6);
} else if(line.indexOf("Number: ") != -1) {
Log.v(this.toString(), "Found number in the string.");
userNumber = line.substring(8);
} else if(line.indexOf("Email ID: ") != -1) {
Log.v(this.toString(), "Found email in the string.");
userEmailID = line.substring(10);
}
}
Log.v(this.toString(), "User credentials = " + userName + " " + userNumber + " " + userEmailID);
} catch (IOException e) {
Log.v(this.toString(), "IOException caught.");
}
} catch (FileNotFoundException e1) {
Log.v(this.toString(), "File not found for reading.");
}
}
The LogCat output shows:
04-14 15:20:43.789: V/com.sriram.htmldisplay.htmlDisplay#44c0c660(675): Written everything to userCredentials.txt
04-14 15:20:43.789: V/com.sriram.htmldisplay.htmlDisplay#44c0c660(675): File not found for reading.
04-14 15:20:43.889: V/com.sriram.htmldisplay.fireflymenu#44c401e0(675): File not found for reading.
My question(s):
1. I need to write the file to internal storage. Am I doing it correctly?
2. Why is the file just written not being read?
Some things for your code:
#Oren is correct, you should use Log.e(TAG, "message", e) instead of the auto-created stuff from eclipse!
you should simply merge the 3 try/catch to one. No need to make it 3 times...
you should use Log.e() as said above for your FileNotFoundException too, so see the stacktrace to check the real reason (which currently covers the hint to solve your issue)
If you would have done at least number 3, you would have seen that the file you try to read could not be found. Thats why your log doesn't show the Can open userCredentials for reading from. output from your if statement.
The reason for that is pretty simple: You create the file by using openFileOutput(userCredFile, MODE_PRIVATE);. If you read the documentation of openFileOutput you will stumble upon:
The name of the file to open; can not contain path separators.
That means that userCredFile can only be something like test.txt. Also this method creates a file in a directory that can't be easily access from "outside".
When you now try to read the file via FileReader(userCredFile) it should be obvious, that android will try to open it in the root directory: /text.txt and it will, of course, fail. No non-root app can write/read in the root directory.
The main question, and also the answer to your issue: Why don't you use the corresponding openFileInput(userCredFile) method to read the file?

Categories