I have a class Book(), Author() and a class CollectionOfBooks()(where I stock all the books in an ArrayList). Then I have my interface where I have a menu where I can add/list/remove/search books. Everything works fine. But, I also want to save my books in a file when I exit the program so when the program ends I call this method(BooksIO() is the class for serialize&deserialize):
public void exitProgram() throws IOException{
System.out.println("Program shuts down, cya!");
BooksIO.outputFile(); // to save my books to the file
}
I am not sure if the books are saved because when I start the program the books don't show up:
public static void main(String[] args) throws IOException, ClassNotFoundException {
UserInterface menu = new UserInterface();
BooksIO.inputFile(); // get the books from the saved file to the library
menu.run();
}
I am not sure what I am doing wrong, can someone help me?
The class for Serialize & DeSerialize :
public class BooksIO {
public static void outputFile() throws IOException{
CollectionOfBooks library = new CollectionOfBooks(); //where the books are saved in an ArrayList
FileOutputStream fout=null;
ObjectOutputStream oos=null;
try{
fout = new FileOutputStream ("stefi.ser");
oos=new ObjectOutputStream(fout);
// I try to save my library to the file
oos.writeObject(library.Books);
System.out.println("Serializing successfully completed");
for(Book c: library.Books){
System.out.println(c.toString());
}
} catch (IOException ex){
System.out.println(ex);
}finally{
try{
if(fout!=null) fout.close();
if(oos!=null) oos.close();
} catch (IOException e){
}
}
}
public static void inputFile() throws IOException, ClassNotFoundException{
CollectionOfBooks library = new//where my books are saved in an ArrayList of type Book CollectionOfBooks();//where my books are saved in an ArrayList of type Book
ObjectInputStream ois = null;
try{
FileInputStream fin = new FileInputStream("stefi.ser");
ois = new ObjectInputStream(fin);
// try to get my books from the file and save it in the library
library.Books = (ArrayList<Book>)ois.readObject();
System.out.println("Deserializing successfully completed");
for(Book c: library.Books){
System.out.println(c.toString());
}
}catch (ClassNotFoundException e){
System.out.println("The class for this type of objects"+
"does not exist in this application!");
throw e;
}finally{
try{
if(ois!=null){
ois.close();
}
}catch (IOException e){
}
}
}
}
Right at the top of your outputFile() method, you are initializing a "library" variable to a new (presumably empty) CollectionOfBooks, and then serializing that.
What you want to do instead is pass the application's instance of CollectionOfBooks into the outputFile() method, and serialize that.
Also, while others may disagree, I find Java serialization to be a bit clunky, and it has some odd edge cases that you need to be aware of. I personally wouldn't use it unless I had to for some reason - I'd use a JSON serialization library, like perhaps GSon, instead.
Just guessing because your question does not include a valid MCVE program yet, but it appears that you're reading in the books but not getting them to where they belong, to the main GUI, quite possibly the UserInterface class (we don't no, since you've not shown us). If so...
Give the UserInterface class a public void updateBooks(CollectionOfBooks books) method, and call this with the updated book collection:
public void updateBooks(CollectionOfBooks collectionOfBooks) {
this.collectionOfBooks = collectionOfBooks;
}
Change inputFile to return a CollectionOfBooks object:
public static CollectionOfBooks inputFile() throws IOException, ClassNotFoundException{
//...
}
and then return the collection.
Then in main you could do:
public static void main(String[] args) throws IOException, ClassNotFoundException {
UserInterface menu = new UserInterface();
menu.updateBooks(BooksIO.inputFile());
menu.run();
}
Related
This program is run when there is no extant file named "Test Object.to". The output of this program is "IO caught". Why?
import java.io.*;
public class Test
{
public static void main (String [] args)
{
TestObject testObject = new TestObject("Test Object");
try
{
saveTestObject(testObject);
}
catch (FileNotFoundException fnf)
{
System.out.println("FNF caught");
}
catch (IOException io)
{
System.out.println("IO caught");
}
}
static void saveTestObject(TestObject to) throws FileNotFoundException, IOException
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(to.name + ".to"));
oos.writeObject(to);
oos.close();
}
}
class TestObject
{
String name;
TestObject(String s)
{
name = s;
}
}
First of all, this does not throw a FileNotFoundException, since as per the docs, FileOutputStream's constructor will create the file if it doesn't exist instead of throwing an error. If you print the error, you see:
java.io.NotSerializableException: TestObject
Again, as per the docs, writeObject requires that its argument be Serializable. Since Serializable is just a marker interface, you can just implement it:
class TestObject implements Serializable
and now your code doesn't throw any errors.
Ok I see now that TestObject obviously needs to implement Serializable
so i created an ArrayList of Point objects but when i'm using the get() method of the ArrayList it seems that it does not return Point object.. why is this happening?
public class SkylineDC {
public static void openAndReadFile(String path,ArrayList pointsList){
//opening of the file
Scanner inputFile=null;
try{
inputFile=new Scanner(new File(path));
}
catch (Exception e1){
try{
inputFile=new Scanner(new File(path+".txt"));
}
catch (Exception e2){
System.out.println("File not found..");
System.exit(1);
}
}
//reading of the file
short listSize=inputFile.nextShort();
pointsList=new ArrayList<Point>(listSize);
//pointsList.add(new Point(10,10));
//System.out.println("Size of List:"+pointsList.size());
pointsList.get(0).
}
public static void main(String[] args) {
String path=args[0];
ArrayList totalPoints=null;
openAndReadFile(path,totalPoints);
//System.out.println("finish");
}
}
ArrayList pointsList
you're using a raw type in the declaration.
Change it to ArrayList<Point> pointsList
Also:
ArrayList totalPoints=null should not be the raw type either. Change to ArrayList<Point> totalPoints = new ArrayList<>()
I would furthermore suggest simply having your method return a List<Point> rather than trying to populate an existing list. I don't even know if the code you currently have will run as expected. My suspicion is that it will not.
I am performing a project, where so far in the discipline, we can not use database to persist the data. I am persisting the data in .tmp files. The first time I persisted the list of doctors, and it worked, but now that I'm trying to persist the patient user data, but this error happens, that file is not found.
These are my load, anda save methods in the class "SharedResources":
public void loadUserPatient(Context context) {
FileInputStream fis1;
try {
fis1 = context.openFileInput("patient.tmp");
ObjectInputStream ois = new
ObjectInputStream(fis1);
userPatient = (UserPatient) ois.readObject();
ois.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
public void saveUserPatient(Context context) {
FileOutputStream fos1;
try {
fos1 = context.openFileOutput("patient.tmp",
Context.MODE_PRIVATE);
ObjectOutputStream oos =
new ObjectOutputStream(fos1);
oos.writeObject(userPatient);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
here is the whole class: https://ideone.com/f3c74u
the error is happening on line 16 of MainActivity:
SharedResources.getInstance().loadUserPatient(this);
here is the whole class "Main": https://ideone.com/OyiljP
And I think this error is ocurring because of the 52nd line of the UserPatientAdd class:
SharedResources.getInstance().getUserPatient();
because when I work with an ArrayList, I put an add at the end of the line, like:SharedResources.getInstance().getDoctors().add(doctor);
And I get confused on how to proceed when I deal only with a user.
This is the whole UserPatientAdd class: https://ideone.com/clUSa3
How can I solve this problem?
You need to set the UserPatient using something like this
In your SharedResources class, create a new method:
public void setUserPatient(UserPatient user) {
userPatient = user;
}
Then in your UserPatientAdd class set the new object:
UserPatient userPatient = new UserPatient (birth, name, bloodType, bloodPressure, cbpm, vacinesTaken, vacinesToBeTaken,
allergies,weight, height, surgeries, desease);
SharedResources.getInstance().setUserPatient(userPatient);
Done
I am trying to write an ArrayList of Question objects called questions to a file, then reading the file.
My problem is that when I am reading the file, it gives me an error that says: java.lang.ClassCastException: java.lang.String cannot be cast to Question at Quiz.load
My question is, why is this problem occurring and how can I fix it? I've been reading a lot of tutorials and they just cast the object to the class name which is what I did. I included my save & load functions.
Inside Quiz class:
Write Objects To File
ArrayList<Question> questions = new ArrayList<>();
//filename given by user
FileOutputStream fos = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(questions);
Read Objects From File
ArrayList<Question> readQuestions = new ArrayList<>();
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.print("QUIZ LOADING...");
readQuestions.add((Question)ois.readObject()); //problem occurs
Imagine that you have an empty box. You put an apple into the box.
Then you close it, and open it later on. Now, do you think it would work out to expect to find a hamburger in that box?
But that is what you are doing - storing a String and expecting to find a Question object. And that class cast exceptional is how the jvm tells you about reality not fitting your assumptions.
Solution: either store question objects - or expect strings to come back when reading the file.
You are serializing a list and deserializing it with Question.
Just change
readQuestions.add((Question) ois.readObject()); //problem occurs
with this
readQuestions = (ArrayList<Question>) ois.readObject();
Further explanation :
When i tried the example i got this error :
java.lang.ClassCastException: java.util.ArrayList cannot be cast to Question
So most likely if you are getting ClassCastException with String, you are also missing Serializable interface on Question. Something like this :
class Question implements Serializable {
String text;
public Question(String text) {
this.text = text;
}
}
Adding working code :
import java.io.*;
import java.util.ArrayList;
public class ObjectIS {
public static void main(String[] args) {
new ObjectIS().save();
new ObjectIS().load("abcd");
}
public void save() {
try {
ArrayList<Question> questions = new ArrayList<>();
questions.add(new Question("what is your name"));
//filename given by user
FileOutputStream fos = new FileOutputStream("abcd");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(questions);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void load(String filename) {
try {
ArrayList<Question> readQuestions = new ArrayList<>();
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.print("QUIZ LOADING...");
// readQuestions.add((Question) ois.readObject()); //problem occurs
readQuestions = (ArrayList<Question>) ois.readObject();
System.out.println("ois = " + readQuestions);
ois.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassCastException e) {
e.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}
class Question implements Serializable {
String text;
public Question(String text) {
this.text = text;
}
#Override
public String toString() {
final StringBuffer sb = new StringBuffer("Question{");
sb.append("text='").append(text).append('\'');
sb.append('}');
return sb.toString();
}
}
It is exactly as I said. You are serialising a String:
oos.writeObject(questions.toString());
And then attempting to deserialize it as a Question, which it never was:
(Question)in.readObject();
Solution:
remove the .toString() part.
deserialize as a List<Question>, which is what it really will be.
the following code is incomplete but the main focus of my question is on the method processConfig() anyway. It reads the properties out of a file and I want to handover these properties to the method replaceID(). It worked already when the content of processConfig was in the main()-method. But now I wanted to put this code into it´s own method. What is the best way of handing over the properties (which I saved in Strings like difFilePath). I´m not that familiar with OO-programming and want to understand the concept. Thanks for your help.
public class IDUpdater {
....
public static void main(String[] args) throws Exception {
//Here I want to call the variables from processConfig() to make them available for replaceID(...)
replaceID(difFilePath, outputDifPath, encoding);
}
public static void replaceID(String difFilePath, String outputDifPath, String encoding) throws Exception{
return record;
}
public void processConfig(){
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("config.properties");
} catch (Exception e) {
logger.error("File 'config.properties' could not be found.");
}
try {
prop.load(input);
} catch (Exception e) {
logger.error("Properties file could not be loaded.");
}
String difFilePath = prop.getProperty("dif_file_path");
String outputDifPath = prop.getProperty("output_dif_path");
String encoding = prop.getProperty("encoding");
}
}
You've to declare your variables globally. This way they can be accessed in each method. After you've declared them globally you first call your processConfig in your main method, which will set your variables to what they should be.
public class IDUpdater {
private String difFilePath;
private String outputDifPath;
private String encoding;
public void main(String[] args) throws Exception {
processConfig();
replaceID();
}
public void replaceID() throws Exception{
// You can use your variables here.
return record;
}
public void processConfig(){
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("config.properties");
} catch (Exception e) {
logger.error("File 'config.properties' could not be found.");
}
try {
prop.load(input);
} catch (Exception e) {
logger.error("Properties file could not be loaded.");
}
difFilePath = prop.getProperty("dif_file_path");
outputDifPath = prop.getProperty("output_dif_path");
encoding = prop.getProperty("encoding");
}
}
Note that I declared the variables privately. For more information about protecting your variables see https://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx.
You may want to read an article (or even better yet - a book) on topic of encapsulation and objects. This or this may be a good starting point for you. There is no point in anyone fixing your code, if you don't understand the concepts behind it.