java - Serialization overwrites - java

I got a problem with Serialization and Deserialization in java. In my program whenever I create a file then I also creating a fileInfo object and then I serializing in a secure_store.dat file and after deserializing from that file also.For example I can create test1.txt with a new fileInfo object and serialize that fileInfo object then i can create test2.txt with again different fileInfo object and serialize it also without a problem. Whenever i deserialize the secure_store.dat I can easily see that 2 objects but the problem is whenever i close the program and reopen the program and create test3.txt with a fileInfo object and try to serialize, it deletes the 2 old object in the secure_store.dat file and whenever I deserialize the file I can only see the last object the others always deleted(which are created before the program closes). How i can solve this problem and return the all three objects ? Below you can see my code...
public static void serialization(ArrayList<FileInfo> allFiles) {
try {
FileOutputStream fileOut = new FileOutputStream("secure_store.dat");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(allFiles);
out.close();
fileOut.close();
} catch (IOException i) {
i.printStackTrace();
}
}
#SuppressWarnings("unchecked")
public static ArrayList<FileInfo> deSerialization() throws FileNotFoundException {
ArrayList<FileInfo> arraylist = new ArrayList<FileInfo>();
try {
FileInputStream fileIn = new FileInputStream("secure_store.dat");
ObjectInputStream in = new ObjectInputStream(fileIn);
arraylist = (ArrayList<FileInfo>) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
return arraylist;
} catch (ClassNotFoundException c) {
System.out.println("Class not found");
c.printStackTrace();
return arraylist;
}
return arraylist;
}

Related

How to ensure the cast checked before serialization

I've built the project and I serialized the ArrayList of objects. It works, but I know it cannot guarantee when deserializing (reading) back the ArrayList. It might encounter the ClassCastException How can I do the safe type check when serializing or deserializing?
I've referred to:
Type safety: Unchecked cast from Object to ArrayList<MyVariable>
How to perform a checked cast?
But still confused...
Any help is highly appreciated.
Here is part of my code:
public void saveData() {
if (playerList.size() != 0) {
try {
FileOutputStream fileOut =
new FileOutputStream("players.dat.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(playerList);
out.close();
fileOut.close();
//System.out.printf("Serialized data is saved in players.dat.ser");
} catch (IOException i) {
i.printStackTrace();
}
} else {
System.out.println("There is no data to be stored.");
}
}
And the code when loading back
public void loadData() {
try {
FileInputStream fis = new FileInputStream("players.dat.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
ArrayList<NimPlayer> newPlayerList = (ArrayList<NimPlayer>)ois.readObject();// warning here
setPlayerList(newPlayerList);
ois.close();
fis.close();
} catch (IOException i) {
//i.printStackTrace();
return;
} catch (NullPointerException n) {
//System.out.println("no data to be recoverd.");
//n.printStackTrace();
} catch (ClassNotFoundException c) {
//System.out.println("players.dat file not found");
//c.printStackTrace();
return;
}
}
Because of type erasure, the best you can say is that it's a raw ArrayList, via instanceof. You can't do any checks against the generic type parameter.
If you want to do it safely then you can do something like this, checking every single item and creating a new list, but there is an overhead involved.
Object read = ois.readObject();
List<NimPlayer> newPlayerList = new ArrayList<>();
if (read instanceof List) {
for (Object item : (List<?>) read) {
if (item instanceof NimPlayer) {
newPlayerList.add((NimPlayer) item);
}
// else { maybe throw exception, or log warning }
}
}
Otherwise, you can suppress the warning.

how to store many objects in a byte array

I am coding in java and I have a problem
I am using an interface (that the teacher gave us and we cant change it), the interface obligate you to implement a function with a byte array is input and through this array you can transfer any data you want.
I need to pass a few different objects with unknown size ,is there a way to do it? I can obviously put the size of every object at the beginning but this is very difficult is there any easier way to do it?
I also need to pass data in a byte array from another language like c or cpp
so the technique must be non specific to java
here is a simple example of what the code looks like
void myFunc(byte[] arr)
{
byte[] name; // arr[0:10] string in ascii
byte[] lastName; //arr[10:k] string in ascii
byte[] currentUnixTime; //arr[k:arr.lenfth] this is an int
some operations.....
}
So without further details you can generically send Object through serialization but it might not always be a good idea. Here is a fairly generic implementation of Object serialization.
interface Sender {
void write(OutputStream outputStream, Object... objects);
List<Object> read(InputStream inputStream);
}
class Homework implements Sender {
#Override
public void write(OutputStream stream, Object... objects) {
for (Object obj : objects) {
try (ObjectOutputStream objStream = new ObjectOutputStream(stream)) {
objStream.writeObject(obj);
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public List<Object> read(InputStream stream) {
List<Object> objectList = new ArrayList<>();
try (ObjectInputStream objStream = new ObjectInputStream(stream)) {
Object obj;
while ((obj = objStream.readObject()) != null) {
objectList.add(obj);
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return objectList;
}
}
Edit: I misunderstood the question. Here is a implementation that uses byte[]s
interface Sender {
byte[] write(Object... objects);
List<Object> read(byte[] bytes);
}
class Homework implements Sender {
#Override
public byte[] write(Object... objects) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (ObjectOutputStream objStream = new ObjectOutputStream(out)) {
for (Object obj : objects) {
objStream.writeObject(obj);
}
objStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();
}
#Override
public List<Object> read(byte[] bytes) {
List<Object> objectList = new ArrayList<>();
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(bytes);
try (ObjectInputStream objStream = new ObjectInputStream(byteInputStream)) {
Object obj;
while ((obj = objStream.readObject()) != null) {
objectList.add(obj);
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return objectList;
}
}
Then to use it.
Homework homework = new Homework();
String helloWorld = "hello world";
byte[] helloBytes = homework.write(helloWorld);
assert homework.read(helloBytes).get(0).equals(helloWorld);
In the end what I did was this -
I converted to base 32 every object that I wanted to send ,then in between each converted object I added a ',' to separate the object (since ',' isn't needed for base 32 representation).
after that the analysis was simple

Android: File not found exception, it worked in the first time?

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

Reading objects from a file ClassCastException error

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.

Creating a position file using ObjectOutputStream

I have a HashMap where i store last read time of multiple sources which i needs to be backed up to a file. The same hashmap is updated regularly and should be backed up every time.
I am using ObjectOutputStream for this, as the same object is updated i was doing a reset() on the ObjectOutputStream, so that the file is updated, but with this is see and for every writeObject() a new line is written to the file this should be because the object is appended to the file. My service is long running service, so i can't afford the object to be appended every time as that will cause the file to become huge.
Here is a snippet of my code
public void open() throws WCException {
try {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(bookmarkFile));
bookmarks = (HashMap<String, Long>) objectInputStream.readObject();
objectInputStream.close();
} catch (ClassNotFoundException | IOException e) {
}
try {
fileOutputStream = new FileOutputStream(bookmarkFile);
objectOutputStream = new ObjectOutputStream(fileOutputStream);
} catch (IOException e) {
throw new WCException("Bookmarker", e.getCause());
}
}
public void close() throws WCException {
try {
objectOutputStream.close();
fileOutputStream.close();
} catch (IOException e) {
throw new WCException("Bookmarker", e.getCause());
}
}
public synchronized void write() throws WCException {
try {
objectOutputStream.writeObject(bookmarks);
objectOutputStream.reset();
} catch (IOException e) {
throw new WCException("Bookmarker", e.getCause());
}
}
public synchronized void update(HashMap<String, Long> bookmark) {
for (Map.Entry<String, Long> entry : bookmark.entrySet()) {
if (!bookmarks.containsKey(entry.getKey()))
bookmarks.put(entry.getKey(), entry.getValue());
else {
long last = bookmarks.get(entry.getKey());
if (last < entry.getValue())
bookmarks.put(entry.getKey(), entry.getValue());
}
}
}
I want something with which there is always a simple object in the file, which is latest. I am even ok with going away from ObjectOutputStream.

Categories

Resources