How to get array.length after it has been deserialized [duplicate] - java

This question already has answers here:
why does the catch block give an error with variable not initialized in Java
(7 answers)
Closed 6 years ago.
So, I'm working on a project that automates everything from character sheets to dice rolls for a table top RPG I like to play. I'm trying to store character data (character name, 2 arrays of stats, and 2 arrays of those stat values) that can be accessed at the start of executing the app. This has been very helpful so far.
However, I'd also like to display the name and stats so the user can confirm that this is the character data they want to use. And I'm having trouble displaying the data in a readable format. Here's my code (you'll find the problem I'm having toward the bottom, although if you see anything else that could be optimized along the way, I would appreciate any feedback :-)":
import java.io.*;
import javax.swing.JOptionPane;
public class fengShuiFiles implements Serializable {//start class
private FileOutputStream outFile;
private ObjectOutput objectWriter;
private FileInputStream inFile;
private ObjectInputStream objectReader;
public void WriteFile(String fileNameIn, String[] sArray1, String[] sArray2,
String[] sArray3, String[] sArray4) {
try {
outFile = new FileOutputStream(fileNameIn + ".txt", true);
objectWriter = new ObjectOutputStream(outFile);
objectWriter.writeObject(sArray1);
objectWriter.writeObject(sArray2);
objectWriter.writeObject(sArray3);
objectWriter.writeObject(sArray4);
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "I/O occurred during a write operation\nFor more",
"information see console output.",
"Read File", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
} // End try/catch
} // End Open
//not sure if I'll need this. Keeping it for now just in case
//public void writeRecords(String textRecords)
//{
// outFile.close();
// pw.println(textRecords);
//} // End WriteRecords
public void ReadFile(String fileNamein) throws FileNotFoundException {
fengShuiFiles[] sArray1, sArray2, sArray3, sArray4;
try {
inFile = new FileInputStream(fileNamein + ".txt");
objectReader = new ObjectInputStream(inFile);
sArray1 = (fengShuiFiles[]) objectReader.readObject();
sArray2 = (fengShuiFiles[]) objectReader.readObject();
sArray3 = (fengShuiFiles[]) objectReader.readObject();
sArray4 = (fengShuiFiles[]) objectReader.readObject();
} catch (IOException | ClassNotFoundException e) {
JOptionPane.showMessageDialog(null, "I/O error occurred opening a",
"file\nFor more information see console output.",
"Read File", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
} // End try/catch
for (int x = 0; x < sArray1.length; x++) {
}
}
public void closeFile() {
try {
outFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} // End closeFile
}//end class
So, that sArray1.length in the for statement toward the bottom? It's coming up with an error message saying that sArray1 may not have been initialized. And I'm having trouble figuring out why, and how I can get that length so I can print out the arrays in a readable manner. Does anyone have any ideas? Thanks.

You need to initialize local variables. If an exception occurs, it's possible that some or all of the arrays aren't initialized and the compiler won't allow that.
The easiest way to get rid of the error is to initialize the arrays to null, but your program has a logic problem. You're catching the exceptions and continuing, even though there's no way your program can work correctly after that. You should instead throw the exceptions out of the readFile() method and then most likely exit the program. You could also continue as if the file didn't exist, but at least show a warning about it.

You always have to initialize variables in java. You do this in your try block, but if an exception occurs, the array will not have been initialized.
You can move the for loop to the try block:
public void ReadFile(String fileNamein) throws FileNotFoundException {
fengShuiFiles[] sArray1, sArray2, sArray3, sArray4;
try {
...
for(int x = 0; x < sArray1.length; x++) {
}
} catch (IOException | ClassNotFoundException e) {
...
} // End try/catch
}
Or use a default value to initialize the array in the catch block:
public void ReadFile(String fileNamein) throws FileNotFoundException {
fengShuiFiles[] sArray1, sArray2, sArray3, sArray4;
try {
...
} catch (IOException | ClassNotFoundException e) {
...
sArray1 = new fengShuiFiles[0]; // Some default value.
} // End try/catch
for(int x = 0; x < sArray1.length; x++) {
}
}
Something that might be more convenient though, is to return the read arrays, and do something with them in the calling method.
For instance:
public Optional<fengShuiFiles[][]> ReadFile(String fileNamein) throws FileNotFoundException {
try {
fengShuiFiles[] sArray1, sArray2, sArray3, sArray4;
// read the file
return Optional.of(new fenShuiFiles[][]{ sArray1, sArray2, sArray3, sArray4 });
} catch (IOException | ClassNotFoundException e) {
...
return OPtional.empty();
}
}
Then in some other method:
Optional<fengShuiFiles[][]> ret = ReadFile(...);
if(ret.isPresent()) {
for(fengShuiFiles[] arr : ret.get()) {
System.out.println(Arrays.toString(arr)); // Print here
}
}

Related

How to execute all lines in try block before it moves to catch?

I have to read a file in try block and later print it out. While the print method is working, the program is not running the method. How do I solve this? I can't keep it in the while loop.
Lexer.java
private boolean atEOF = false;
private SourceReader source;
public static void main(String args[]) {
Token token;
try {
Lexer lex = new Lexer(args[0]);
while(!(lex.atEOF)) {
token = lex.nextToken();
}
lex.source.printVec(); // WANT TO EXECUTE THIS METHOD
} catch (Exception e) {
System.out.println("usage: java lexer.Lexer filename.x");
System.exit(-1);
}
}
SourceReader.java
public void printVec() {
System.out.println("in the program");
for (String l : progVec) {
System.out.println(l);
}
}
How do I run printVec() after the while loop in Lexer.java?
I would simply declare the Lexer outside of the try-catch block then put the required Function at the first line of the catch part too.
Lexer lex;
try {
lex = new Lexer(args[0]);
while(!(lex.atEOF)) {
token = lex.nextToken();
}
lex.source.printVec();
} catch (Exception e) {
lex.source.printVec();
//... rest of code
}

How to exit java stream.forEach before it complets?

I have this simple code that processes files in a designated folder.
processLog method throws IOException, when this happens I would like to exit (no need to continue processing rest of the files) but sadly I have to catch the exception locally.
try (Stream<Path> filePathStream = Files.walk(Paths.get(logs))){
filePathStream.forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
processLog(filePath.toFile());
}
});
}
Any idea how I can break the loop? Thanks.
If you want to use a Stream specifically, you could do this:
import java.io.IOException;
import java.util.Arrays;
public class Eg {
public static void main(String[] args) {
int[] numbers = new int[] {1,2,3,4,5,6,7,8};
Arrays.stream(numbers).takeWhile(i -> process(i)).forEach(b ->{});
}
private static boolean process(int i) {
try {
if (i == 6) {
throw new IOException();
}
System.out.println("processed " + i);
return true;
} catch (IOException e) {
System.out.println("failed on " + i);
return false;
}
}
}
The final empty forEach is to force the Stream to be run. You could return a different type if there was something you wanted to do with the results of processing the files.
I think the easiest/cleanest solution is to convert the Stream to an Iterator. Then you can use a "normal" loop which can throw a checked exception. For example:
try (Stream<Path> filePathStream = Files.walk(Paths.get(logs))) {
// you can filter here instead of in an 'if' block later
Iterator<Path> itr = filePathStream.filter(Files::isRegularFile).iterator();
while (itr.hasNext()) {
processLog(itr.next().toFile());
}
} catch (IOException ex) {
// you've now stopped processing
// do something with 'ex'...
}
try (Stream<Path> filePathStream = Files.walk(Paths.get(logs))){
filePathStream.forEach(filePath -> {
if (Files.isRegularFile(filePath))
processLog(filePath.toFile());
});
}catch (IOException e){
e.printStackTrace();
}
Add just catch to get the exception, forEach will stop when processLog throw the Exception
My last answer was wrong.
Similar question has been asked before.

How to overwrite a file that is altering an arraylist

I'm writing a program in order to keep track of DVDs in my library. I'm having trouble altering the text file that saves an added or removed DVD object from the arraylist. Whenever I call my save method, which is the one that overwrites the existing text file holding all the information, it will not change it whatsoever. My add and remove methods work fine but it's just the save method which overwrites the file that I'm reading from that will not work. The following code is what I was attempting to use to save the arraylist to the file. My filename is DVDCollection.txt and the boolean variable flag is a static variable used to check whether or not the code which adds or removes an object from the arraylist was reached.
public void save() {
try{
if(flag=true){
FileWriter instream = new FileWriter("DVDCollection.txt",false);
instream.close();
}else{
return;
}
}catch(IOException e){
System.out.println("The file could not be written to!");
}
}
If you are using java 8 or above it's as simple as:
List<String> lines = Arrays.asList("first line", "second line");
try {
Files.write(Paths.get("my-file.txt"), lines);
} catch (IOException e) {
//handle exception
}
Make sure you provide the right path!
Not sure, why this method should save an array list, as the actual code that writes to this file is missing. Here is simple test, let's start here:
import java.io.*;
import java.util.*;
public class FileSaveTest {
public static void main(String[] args) {
FileSaveTest test = new FileSaveTest();
test.fill();
test.save();
}
public void fill() {
arrayList.add("My disc 1");
arrayList.add("My disc 2");
arrayList.add("Another disc");
}
public void save() {
try {
if(flag) { // you dont need ==true
FileWriter instream = new FileWriter("DVDCollection.txt",false);
for (String entry : arrayList) {
instream.write(entry + "\n");
}
instream.close();
} else {
return;
}
} catch(IOException e) {
System.out.println("The file could not be written to!");
}
}
private ArrayList<String> arrayList = new ArrayList<>();
private static boolean flag = true;
}
Next, it's not very good, to close the file in such manner. If an exception occurs while writing, the file will not be closed. instream.close() should be put into the "finally" block. This block will be executed in any case, regardless of whether an exception occurred or the return keyword met:
public void save() {
Writer instream = null;
try {
if(flag) { // you dont need ==true
instream = new FileWriter("DVDCollection.txt",false);
for (String entry : arrayList) {
instream.write(entry + "\n");
}
} else {
return;
}
} catch(IOException e) {
System.out.println("The file could not be written to!");
} finally {
try {
if (instream != null)
instream.close();
} catch (IOException e) {
System.err.println("Exception during close");
}
}
}
Or, if you are using java 7, you can use try-with-resources syntax:
public void save() {
if(flag) { // you dont need ==true
try (Writer instream = new FileWriter("DVDCollection.txt",false)) {
for (String entry : arrayList)
instream.write(entry + "\n");
} catch(IOException e) {
System.out.println("The file could not be written to!");
}
} // you dont need "return else { return; }" anymore
}

Run Java program after exception encountered

How can I make my Java run again from the start (main) when it encounters an exception without closing and running it again manually?
My program basically writes on a file. When it cannot find the file I will throw the FileNotFoundException then write the file (say for example hello.txt). After it writes, the program closes (in NetBeans cause I am still developing it) and start showing this at the buttom:
Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:542)
at java.lang.Integer.parseInt(Integer.java:615)
at app4pics1word.App4pics1word.cache(App4pics1word.java:127)
at app4pics1word.App4pics1word.<init>(App4pics1word.java:18)
at app4pics1word.App4pics1word.main(App4pics1word.java:146)
Java Result: 1
you can try this
public static void main(String[] args) {
try {
//something wrong happens here
}catch(Throwable e) {
e.printStackTrace();
main(args);
}
}
You should use exception handling instead of restarting the program. If you restart the program, the error will still be there and thus your program will keep on trying to run for eternity, always failing with the same exception.
You would like to catch your exception and make sure that the input is valid:
boolean okInput = false;
int x = -1;
String someData = "rr";
do {
try {
x = Integer.parseInt(someData); // try to parse
okInput = true;
} catch(NumberFormatException n) {
// Error, try again
okInput = false
someData = "2";
}
} while(!okInput); // Keep trying while input is not valid
// Here x is a valid number
This tutorial provides you good code in general of how exceptions work.
is this what you are looking for ?
public static void main(String [] args) {
boolean done = false;
do {
try {
writeSomeFile();
done = true;
}
catch (Exception ex)
{
System.out.println("Exception trapped "+ex)
}
} while (!done);
}
You can make it a loop that is broken only when the try block succeeds without an Exception:
public static void main(String[] args) {
while(true) {
try {
...
break; //at the end of try block
}
catch (SomeException e) {
//print error message here, or do whatever
}
}
//program continues here once try block gets through w/o exceptions
...
}
However, instead of having this in your main I recommend hiding this rather ugly structure inside a method.

Infinite Loop when looping through FileInputStream

Alright, so I am writing a Java application to import a csv file and then loop through the results, and load them into an array. I am importing the file correctly because it doesn't through an Exception. My issues is that when I try to count the number of records in the FileInputStream I am trapped in an infinite loop. What could be the issue here. Heres the code:
This is my class with a Main method which calls go():
public void go() {
pop = new PopularNames();
popGui = new PopularNamesGui();
String file = popGui.userInput("Enter the correct name of a file:");
pop.setInputStream(file);
pop.getNumberOfNames();
}
This is the class PopularNames (pop), and in the below method I am setting the inputStream var to a new FileINputStream. The file name is provided by the user.
public void setInputStream(String aInputStream) {
try {
inputStream = new Scanner(new FileInputStream(aInputStream));
} catch (FileNotFoundException e) {
System.out.println("The file was not found.");
System.exit(0);
}
}
This is the trouble method. Where I am simply looping through the FileInputStream and counting the number of records:
public void getNumberOfNames() {
while (this.inputStream.hasNext()) {
fileDataRows++;
}
}
public void getNumberOfNames() {
while (this.inputStream.hasNext()) {
inputStream.nextLine(); // Need to read it so that we can go to next line if any
fileDataRows++;
}
}

Categories