Serializing objects with hashMap - java

This is my first time i try objects serializing.
My problem is that when i call for saving new objects(Reminder.java objects) it saves them in the hash map but when i load it gives me the properties of the last saved object.
So my question is:
1.Saving - How do i "append" objects to a file ?
2.Loading - how to iterate through them and get the right object (using the key class type MyDateClass)
. Example will be welcomed. Thank you.
public void save(MyDateClass chosenDate, String string){
System.out.println("Trying to save");
reminderMap.put(chosenDate, string);
//serializing an object :
this.dateReminder = chosenDate;
this.reminder = string;
try
{
FileOutputStream fileOut =
new FileOutputStream("/tmp/reminder.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(this);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/reminder.ser. ");
}catch(IOException i)
{
i.printStackTrace();
}
}
public String Load(MyDateClass chosenDate){
System.out.println("Trying to load");
this.reminder = reminderMap.get(chosenDate);
System.out.println(this.reminder);
// deserialize
Reminder e = null;
try
{
FileInputStream fileIn = new FileInputStream("/tmp/reminder.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Reminder) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
}catch(ClassNotFoundException c)
{
c.printStackTrace();
}
return e.reminder;
}
}

I did a demo and unit test for you, currently I use java.util.Date to substitute your SomeDate class .
update: 2013-12-31
I am not trying to make things complex,but I really feel it is my responsibility to not mislead others,so I try to fixed the code again.Currently, HashMap can't be append,please improve it.Thanks!
this code refactored from your code:
import java.io.*;
import java.util.*;
/**
* refactored by your code
* append object stream haven't realized,please help
* 2013-12-31
*/
public class Reminder implements Serializable {
public static void main(String[] args) {
//do some initialization
Reminder re = new Reminder();
re.put(new Date(System.currentTimeMillis()), "Hope it work!");
re.put(new Date(System.currentTimeMillis()+100), "it work!");
re.put(new Date(System.currentTimeMillis()+200), "Wake up!");
//save to file ,using append mode
String filpath = "/tmp/reminder.ser";
re.save(filpath,true);
//load from file and iterate the key-value pair
Reminder reLoad = Reminder.Load(filpath);
if(reLoad != null) {
Iterator<Map.Entry<Date,String>> it = reLoad.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<Date,String> entry = it.next();
System.out.format("reminder: %tc---%s%n",entry.getKey(),entry.getValue());
}
}
}
public Set<Map.Entry<Date,String>> entrySet() {
return reminderMap.entrySet();
}
public void put(Date chosenDate, String string) {
reminderMap.put(chosenDate, string);
}
public String get(Date chosenDate) {
return reminderMap.get(chosenDate);
}
/**
* serializing an object
* #param filePath path to save file
* #param append indicate whether append or not
*/
public void save(String filePath,boolean append){
System.out.println("Trying to save");
try
{
ObjectOutputStream out = new ObjectOutputStream
( new FileOutputStream(filePath,append));
out.writeObject(this);
out.close();
System.out.printf("Serialized data is saved in "+filePath);
}catch(IOException e)
{
e.printStackTrace();
}
}
/**
* deserialize ,load from file and rebuild object
* #param filePath the path from where to load
* #return a new Object
*/
public static Reminder Load(String filePath) {
System.out.println("Trying to load");
Reminder reminder = null;
try
{
ObjectInputStream in = new ObjectInputStream
(new FileInputStream(filePath));
reminder = (Reminder) in.readObject();
in.close();
}catch(IOException | ClassNotFoundException e)
{
e.printStackTrace();
}
return reminder;
}
private static final long serialVersionUID = 1L;
private Map<Date,String> reminderMap = new HashMap<>();
}

Related

How to implement Version Control in Java Serialization Using Same SerialUid?

I have following class that implements serialization.
class User implements Serializable{
public User(String username, String password) {
this.username=username;
this.password=password;
}
private static final long serialVersionUID = 1L;
String username;
String password;
}
I try to save the User class object in a text file with following code.Basically I try to write the object and then read it.
public class SerializableExample {
public static void main(String[] args) {
User user = new User("userB","passwordB");
String filename = "E:\\Proj-docs\\userFile.txt";
FileOutputStream file;
try {
file = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(file);
out.writeObject(user);
out.close();
file.close();
} catch (IOException e) {
e.printStackTrace();
}
User user2=null;
try {
FileInputStream file2 = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(file2);
user2= (User) in.readObject();
Optional checkNull = Optional.ofNullable(user2);
if(checkNull.isPresent()) {
System.out.println(user2.username + " "+user2.password);
}else {
System.out.println("Null Object");
}
}catch(IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
it gives the output userB passwordB
Now let's say I want to change my user object and store it in that same text file
public class SerializableExample {
public static void main(String[] args) {
User user = new User("userD","passwordD");
String filename = "E:\\Proj-docs\\userFile.txt";
FileOutputStream file;
try {
file = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(file);
out.writeObject(user);
out.close();
file.close();
:
:
:
Now if I read my User object it gives userD passwordD
My question is even after updating my user is there a way I can retrieve the old version of user (one with values userB passwordB) using serialVersionUID ? I want to see how version control can be used in Java serialization when we are updating the object or adding new attributes to our class and not changing serial uid.
Thanks in advance for your input.

EOFException when I extract the Object Input/Out put Stream

I use ObjectInput/Output to initialize the hashmap named temp and it put all entry of the hashmap called map that is initialized to new and then use OutputStream to save it in file formatting is .ser
this work perfectly...
import java.io.*;
import java.util.HashMap;
public class PlayerInfo implements Serializable {
ObjectOutputStream out;
ObjectInputStream in;
File userData =new File("path.ser");
HashMap map ;
HashMap temp;
private Integer ID;
String name ;
boolean isItNull =false;
public static void main(String[] args) {
new PlayerInfo();
}
PlayerInfo(){
try {
initializeHashMap();
}catch (Exception e){
e.printStackTrace();
}
}
#SuppressWarnings("unchecked")
private void initializeHashMap(){
try {
//initialize ObjectInputStream in same method when I use it and close it then
in =new ObjectInputStream(new FileInputStream(userData));
if (isItNull){
temp =new HashMap<Integer,PlayerInfo>();
}else {
map =new HashMap<Integer,PlayerInfo>();
temp = (HashMap<Integer, PlayerInfo>) in.readObject();
in.close();
}
}catch (Exception e){
isItNull =true;
initializeHashMap();
}
}
private void getInfo(){
System.out.println("Ok we are in get info so write your ID:-");
int id = 10;
}
#SuppressWarnings("unchecked")
private void createInfo()throws IOException{
//same here initialize ObjectOutputStreamin same method when I use it and close it then
out =new ObjectOutputStream(new FileOutputStream(userData));
System.out.println("Ok we are in create info so write your ID:-");
ID =10;
String scnS ="Mohammed";
System.out.println("Write your name");
map.put(ID,new PlayerInfo(scnS));
temp.putAll(map);
System.out.println("Saving....");
out.writeObject(temp);
out.close();
}
public PlayerInfo(String name){
this.name =name;
}
}
but this throw EFOException
import java.io.*;
import java.util.HashMap;
public class PlayerInfo implements Serializable {
ObjectOutputStream out;
ObjectInputStream in;
File userData =new File("path.ser");
HashMap map ;
HashMap temp;
private Integer ID;
String name ;
boolean isItNull =false;
public static void main(String[] args) {
new PlayerInfo();
}
PlayerInfo(){
try {
openTheOutPutObjectStreamer();
openTheInPutObjectStreamer();
initializeHashMap();
}catch (Exception e){
e.printStackTrace();
}
}
//here I initialize it in separated method
private void openTheOutPutObjectStreamer()throws IOException{
out =new ObjectOutputStream(new FileOutputStream(userData));
}
//same here I initialize it in separated method
private void openTheInPutObjectStreamer()throws IOException{
in =new ObjectInputStream(new FileInputStream(userData));
}
#SuppressWarnings("unchecked")
private void initializeHashMap(){
try {
if (isItNull){
temp =new HashMap<Integer,PlayerInfo>();
}else {
map =new HashMap<Integer,PlayerInfo>();
temp = (HashMap<Integer, PlayerInfo>) in.readObject();
in.close();
}
}catch (Exception e){
isItNull =true;
initializeHashMap();
}
}
#SuppressWarnings("unchecked")
private void createInfo()throws IOException{
System.out.println("Ok we are in create info so write your ID:-");
ID =10;
String scnS ="Mohammed";
System.out.println("Write your name");
map.put(ID,new PlayerInfo(scnS));
temp.putAll(map);
System.out.println("Saving....");
out.writeObject(temp);
out.close();
}
public PlayerInfo(String name){
this.name =name;
}
}
if you see it the difference is only separate the Object Input/Output to a method and call them
and I am sorry I am a newbie in this website
I don't know a lot about IO but it seems like I cant separate it to methods and call it?
The problem is that in your first code you (correctly) open an input stream uses it and then closes it before doing anything else to the same file but in your second code version you also open the output stream on the same file before having read it and that output stream puts the marker (where to read or write) at the end of the file so when you use your input stream you get an End of file error.
Changing you code to this should work
openTheInPutObjectStreamer();
initializeHashMap();
openTheOutPutObjectStreamer();

Java read a file into an arraylist of objects and return that arraylist

I need to write a class that has two static methods: writeFile and readFile. However, after I do my readFile(), it returns nothing.
class writereadFile {
public static void writeFile(ArrayList<Object> list, File file){
try {
try (FileOutputStream fos = new FileOutputStream(file);ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(list);
oos.close();
}
}catch(IOException e){e.getMessage();}
}
public static ArrayList<Object> readFile(ArrayList<Object>list, File file){
try {
try (FileInputStream fis = new FileInputStream(file);ObjectInputStream ois = new ObjectInputStream(fis)) {
Object o = ois.readObject();
list = (ArrayList<Object>) o;
ois.close();
}
}catch(IOException | ClassNotFoundException e){e.getMessage();}
System.out.println(list);
return list;
}
}
EDIT:
This my class for testing. My object is an arraylist of custom objects if you need the custom object just comment.
class main {
public static void main(String[] args) {
Date date = new Date();
Book b1 = new Book("abc", "Phi", true, date, null);
Book b2 = new Book("cba", "Someone", true, date, null);
Books booklist = new Books();
booklist.add(b1);
booklist.add(b2);
File filetoDo = new File("book.txt");
//write arraylist into file
writereadFile.writeFile(booklist, filetoDo);
//clear the arraylist
booklist.clear();
//read book from file
writereadFile.readFile(booklist, filetoDo);
System.out.println(booklist);
}
}
Your test should read:
bookList = writereadFile.readFile(booklist, filetoDo);
and, by the way, you should really refactor your readFile method to simply:
public static ArrayList<Object> readFile(File file)
You can't modify the argument reference like that, since Java is always pass-by-value call semantics. (You could modify the list argument contents inside the function, but that's not what you are doing.)
If you are using Java 8 try using Streams:
public static readFile(String filePath) {
List<Object> list = new ArrayList<>();
try (Stream<String> stream = Files.lines(Paths.get(filePath))) {
stream.forEach(list::add);
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
I'm playing around this topic a bit on my own, so below you can find some code snippets that might help you.
Examples are very short and simple, so I hope you will not just use e.printStackTrace() in your code :)
public class ExternalIO {
private ExternalIO() {
}
public static ObjectOutputStream objectOutputStream(String basePath, String pathToFile) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(createFileIfDoesNotExist(absolutePath(basePath, pathToFile)));
return new ObjectOutputStream(fileOutputStream);
}
public static ObjectInputStream objectInputStream(String basePath, String pathToFile) throws IOException {
FileInputStream fileInputStream = new FileInputStream(absolutePath(basePath, pathToFile));
return new ObjectInputStream(fileInputStream);
}
private static File createFileIfDoesNotExist(String absolutePath) throws IOException {
File file = new File(absolutePath);
if (file.exists()) {
return file;
}
file.getParentFile().mkdirs();
file.createNewFile();
return file;
}
private static String absolutePath(String basePath, String pathToFile) {
return Paths.get(basePath, pathToFile).toAbsolutePath().toString();
}
}
output usage:
List<ItemType> input = null; //create your input list here
try (ObjectOutputStream objectOutputStream = ExternalIO.objectOutputStream(CONFIG, FILENAME)) {
objectOutputStream.writeObject(input);
} catch (Exception e) {
e.printStackTrace();
}
input usage:
try (ObjectInputStream objectInputStream = ExternalIO.objectInputStream(CONFIG, FILENAME)) {
return (List<ItemType>) objectInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
}
hope that helps ; )

Serializing a list of objects

I am confused on how to serialize and deserialize a list of question objects.
I have a Survey class that has an attribute called Questions, which is a list of Question objects.
I want to be able to serialize the Survey properties, along with all the properties of each question.
Unfortunately I have had no luck so far, here is what I have. Thanks for the help!
public void loadData(Boolean isSurvey) throws FileNotFoundException {
System.out.println("Select a file: ");
FileInputStream fileIn;
if (isSurvey) {
String fileName = listFiles("surveys").get(input.getIntInput(fileCount - 1));
fileIn = new FileInputStream("surveys/" + fileName);
} else {
String fileName = listFiles("tests").get(input.getIntInput(fileCount - 1));
fileIn = new FileInputStream("tests/" + fileName);
}
Question q = null;
try
{
ObjectInputStream in = new ObjectInputStream(fileIn);
q = (Question) in.readObject();
in.close();
fileIn.close();
}catch(IOException i){
i.printStackTrace();
}catch(ClassNotFoundException c) {
System.out.println("Not found");
c.printStackTrace();
}
System.out.println("Deserialized Question...");
System.out.println("prompt: " + q.prompt);
}
public void saveData(Survey survey, Test test, Boolean isSurvey, String fileName) {
try {
File surveyDir = new File("surveys");
File testDir = new File("tests");
if ((!(surveyDir.exists()) && isSurvey)) {
System.out.println("Creating Survey directory. . .");
surveyDir.mkdir();
}
if ((!(testDir.exists())) && !(isSurvey)) {
System.out.println("Creating Test directory. . .");
testDir.mkdir();
}
if (isSurvey) {
FileOutputStream fileOut = new FileOutputStream("surveys/" + fileName);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
for (Question question : survey.questions) {
out.writeObject(survey.questions);
}
out.close();
fileOut.close();
} else {
FileOutputStream fileOut = new FileOutputStream("tests/" + fileName);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
for (Question question : test.questions) {
out.writeObject(question);
}
out.close();
fileOut.close();
}
} catch(IOException i) {
i.printStackTrace();
}
}
Have you already implemented your object to write with the java.io.Serializable
import java.io.Serializable;
public class Question implements Serializable {
//Other codes here
}
Another thing I noticed is that you have written a collection object.
for (Question question : survey.questions) {
out.writeObject(survey.questions);
}
But you are reading it as Question object.
q = (Question) in.readObject();
If the object you wrote is a Collection. Here is an example if it is List collection
q = (List<Question>) in.readObject();

How to handle StreamCorruptedException when using ObjectInputStream? [duplicate]

This question already has an answer here:
StreamCorruptedException: invalid type code: AC
(1 answer)
Closed 5 years ago.
`I am new to java and getting StreamCorruptedException in the code below... In this code I am trying to read multiple objects from a file using ObjectInputStream... m not able to handle the StreamCorruptedException...the o/p I m getting is
File C098.txt already exists
Product ID:- P001
Description:- Book
Price:- Rs.200
Exception in thread "main" java.io.StreamCorruptedException: invalid type code:
AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1374)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at Utility.getProducts(Utility.java:57)
at Utility.main(Utility.java:23)
CODE:
import java.io.*;
import java.util.*;
class Product implements Serializable{
private static final long serialVersionUID = 1L;
String productId;
String desc;
String price;
public Product(String PId,String a_des,String a_price){
productId=PId;
desc=a_des;
price=a_price;
}
public String toString(){
return "Product ID:- "+productId+"\nDescription:- "+desc+"\nPrice:- "+price;
}
}
class Utility{
// Product objProduct;
public static void main(String args[]) throws Exception{
String cartId = "C098.txt";
Product objProduct = new Product("P001","Book","Rs.200");
addProductToCart(cartId,objProduct);
getProducts(cartId);
objProduct = new Product("P087","Laptop","Rs.45,500");
addProductToCart("C098.txt",objProduct);
getProducts(cartId);
}
public static void addProductToCart(String CId,Product p) throws Exception{
try{
boolean searchFile;
File objFile = new File(CId);
searchFile = objFile.exists();
if(searchFile)
System.out.println("File "+CId+" already exists");
else{
objFile.createNewFile();
System.out.println("File "+CId+" did not exist. It is now created");
}
FileOutputStream objFOS = new FileOutputStream(objFile,true);
ObjectOutputStream objO = new ObjectOutputStream(objFOS);
objO.writeObject(p);
objO.flush();
objO.close();
}catch(Exception e)
{
System.out.println("Exception Caught");
}
}
public static void getProducts(String CId) throws Exception{
Product objProduct1 = new Product("","","");
File objFile1 = new File(CId);
FileInputStream objFIS = new FileInputStream(objFile1);
ObjectInputStream objI = new ObjectInputStream(objFIS);
Object obj = null;
try{
while((obj=objI.readObject()) != null){
if (obj instanceof Product) {
System.out.println(((Product)obj).toString());
}
}
}catch (EOFException ex) { //This exception will be caught when EOF is reached
System.out.println("End of file reached.");
}finally {
//Close the ObjectInputStream
try{
if (objI != null)
objI.close();
}catch (IOException ex) {
ex.printStackTrace();
}
}
}
}`
The problem is because of header issue, You are appending to same file and while returning second object it throws exception because of headers issue. try to write object in different files, you can rid out of the problem.
SCE Thrown when control information that was read from an object stream violates internal consistency checks.
try
import java.io.*;
import java.util.*;
class Product implements Serializable{
private static final long serialVersionUID = 1L;
String productId;
String desc;
String price;
public Product(String PId,String a_des,String a_price){
productId=PId;
desc=a_des;
price=a_price;
}
public String toString(){
return "Product ID:- "+productId+"\nDescription:- "+desc+"\nPrice:- "+price;
}
// Product objProduct;
public static void main(String args[]) throws Exception{
String cartId = "C0982.txt";
Product objProduct = new Product("P001","Book","Rs.200");
addProductToCart(cartId,objProduct);
getProducts(cartId);
Product objProduct1 = new Product("P087","Laptop","Rs.45,500");
addProductToCart("C0981.txt",objProduct1);
getProducts("C0981.txt");
}
public static void addProductToCart(String CId,Product p) throws Exception{
try{
boolean searchFile;
File objFile = new File(CId);
searchFile = objFile.exists();
if(searchFile)
System.out.println("File "+CId+" already exists");
else{
objFile.createNewFile();
System.out.println("File "+CId+" did not exist. It is now created");
}
FileOutputStream objFOS = new FileOutputStream(objFile,true);
ObjectOutputStream objO = new ObjectOutputStream(objFOS);
objO.writeObject(p);
objO.flush();
objO.close();
}catch(Exception e)
{
System.out.println("Exception Caught");
}
}
public static void getProducts(String CId) throws Exception{
Product objProduct1 = new Product("","","");
File objFile1 = new File(CId);
FileInputStream objFIS = new FileInputStream(objFile1);
ObjectInputStream objI = new ObjectInputStream(objFIS);
Object obj = null;
try{
while((obj=objI.readObject()) != null){
if (obj instanceof Product) {
System.out.println(((Product)obj).toString());
}
}
}catch (EOFException ex) { //This exception will be caught when EOF is reached
System.out.println("End of file reached.");
}finally {
//Close the ObjectInputStream
try{
if (objI != null)
objI.close();
}catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
</pre>
You can't 'handle' it. You have to prevent it. It results from a design error such as using two ObjectOutputStreams on a stream that is read by a single ObjectInputStream, as you are doing here by appending to the file, or writing data other than objects and not reading it symmetrically.

Categories

Resources