I am having trouble deserializing an object from a file in Java in a new session.
I can serialize an arraylist to file, and then deserialize it in the same session, however, if I create a new Main object and try to deserialize the same file that worked in the previous session, the code does not work.
Why would this be?
Here is my code:
public void LoadPersonListFromFile(String Filename)
{
try
{
PersonList = new ArrayList<Person>();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(Filename));
ArrayList<Person> PersonList = (ArrayList<Person>) in.readObject();
in.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void SavePersonFileToFile(String Filename)
{
try
{
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(Filename));
out.writeObject(PersonList);
out.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
EDIT
The DeSerialization seems to be working, because if I do a .size() call on the List in the LoadPersonListFromFile method, I get the value of 2. However, if I call the .size() method on the List outside of the LoadPersonListFromFile method, the .size() is shown as 0. Why would this be? Do I need to copy the deserialized ArrayList into the private field?
I have the following private field to store the ArrayList at the top of the class:
private ArrayList<Person> PersonList;
EDIT2
Got it working. Here is the code:
public void LoadPersonListFromFile(String Filename)
{
try
{
ObjectInputStream in = new ObjectInputStream(new FileInputStream(Filename));
ArrayList<Person> PersonListFromFile = (ArrayList<Person>) in.readObject();
in.close();
PersonList = PersonListFromFile;
}
catch (Exception e)
{
e.printStackTrace();
}
}
It seems that you didn't define a static final long serialVersionUID in Person class. Basically, when you compile a Serializable class that has no serialVersionUID defined in the source code, the Java compiler will define it for you with random value.
To solve the issue, define the following in Person class:
private static final long serialVersionUID = 1L;
Related
here is code for main
public static void main(String[] args) {
Container container= new Container();
Serializator serializator = new Serializator();
container.setvalue("1st val");
serializator.serialization(container);
}
here is code for container
public class Container implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Holds the elements of a container.
*/
private String[] values;
public String[] getvalue() {
return values;
}
public void setvalue(String[] values) {
this.values=values;
}
}
here is code for a serializator
public class Serializator {
public boolean serialization(Container container) {
boolean flag=false;
File file= new File("C:/conatiner.data");
ObjectOutputStream oos = null;
try {
FileOutputStream fos= new FileOutputStream(file);
if(fos != null) {
oos= new ObjectOutputStream(fos);
oos.writeObject(container);
flag=true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return flag;
}
}
Well, the program should be working in a following way: you create a container that has an array of strings,(you can set the values in it) and then the program must serialize it. but the problem is that the tutorial worked with the String value, but not the String[] one. how can i make it understand the String[] value and insert it?
The crashlog is the following
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method setvalue(String[]) in the type Container is not applicable for the arguments (String)
at ua.khpi.oop.taradai06.program6.main(program6.java:7)
"container.setvalue("1st val");"
First, let's focus on the bug:
In the container, you promised you will send an array of string in the function setValue, but you are sending a single string.
There are two things you could do;
keep the container code as it is and send array of strings from main
Change the container code and let setValue get a single string value and add it to the values array
And you main question related with serialisation please check that post
In order to accept both String and String[] as an input parameter to Container::setvalue method, the varargs should be used, then a single String is accepted as an array consisting of one element.
Also, Java naming conventions for getters/setters of Java Beans specify to capitalize the property names after get/set verb: Getter and setter method names are composed of the word get or set, respectively, plus the property name with the first character of each word capitalized, so the methods should be names as getValues/setValues:
// Container class
public void setValues(String... values) {
this.values = values;
}
Then this method can be invoked as follows without additional overloading:
container.setValues(); // empty array new String[0]
container.setValues("a string"); // new String[1]{"a string"}
container.setValues("a", "b"); // new String[2]{"a", "b"}
container.setValues(new String[]{"1", "2", "3"}); // common array
If you promised you'll use the String[] parameter, then you should note that.
The following version of using setvalue does this work perfectly
container.setvalue(new String[] {"1st val","2nd val","3rd val"});
OK I hope I helped you look in the class "Container" in "setvalue" function, you gived it the parameter "1st value"(Its one string) but it needs a String array. So you can replace your code with this:
main class:
public class main {
public static void main(String[] args) {
Container container= new Container();
Serializator serializator = new Serializator();
container.setvalue("1st value", 0);
serializator.serialization(container);
}
}
Container class:
import java.io.Serializable;
public class Container implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Holds the elements of a container.
*/
int AnyNumberYouWant = 100;
private String[] values = new String[AnyNumberYouWant];
public String[] getvalue() {
return values;
}
public void setvalue(String value, int index) {
this.values[index]=value;
}
}
Serializator class
import java.io.*;
public class Serializator {
public boolean serialization(Container container) {
boolean flag=false;
File file= new File("C:/Container/container.data");
ObjectOutputStream oos = null;
try {
FileOutputStream fos= new FileOutputStream(file);
if(fos != null) {
oos= new ObjectOutputStream(fos);
oos.writeObject(container);
flag=true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return flag;
}
}
And I solved another errors that was there in the code. So I tried it and worked correctly. I hope that I helped you.
I have a problem with the serialization and deserialization of objects in Java, and I think it's because I do not really understand how it works. My program consists of some spreadsheets as in Excel, but by console. I have a class "Book" and a class "Page". In Book, I have declared a Page's HashMap and in Page I have a String's Hashmap (to simulate the cells). Now I want that book to be persistent and for that what I do is serialize the "libro" object (Book instance):
try {
FileOutputStream fileOut =
new FileOutputStream("H:\\Users\\thero\\Desktop\\bin\\libro.bin");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(libro);
out.close();
fileOut.close();
System.out.printf("Se ha guardado el libro correctamente");
}
catch (IOException i) {
i.printStackTrace();
}
This code is included in a method of a class called "Salvar" that I call from the main. At the same time I have a class "Cargar" with the opposite method:
try {
FileInputStream fileIn = new FileInputStream("H:\\Users\\thero\\Desktop\\bin\\libro.bin");
ObjectInputStream in = new ObjectInputStream(fileIn);
libro = (Book) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
} catch (ClassNotFoundException ex) {
Logger.getLogger(Cargar.class.getName()).log(Level.SEVERE, null, ex);
}
I also call this method from the main, and when executing it, no exception jumps. However, it seems that it only loads the Book instance, but it does not load the Hashmap property, and therefore it does not load the created spreadsheets with the cells. Where is the problem? This is my class Book code:
package javacalc.items;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Book implements Serializable{
private HashMap<String, Page> libro;
private Page activePage;
private String nameActivePage;
public Book(){
this.libro = new HashMap<>();
}
public List <String> getListPages() {
ArrayList <String> myList = new ArrayList<>();
for (String s: this.libro.keySet())
myList.add(s);
return myList;
}
public void setListPages(String s, Page p) {
this.libro.put(s,p);
}
public void deletePage(String s){
this.libro.remove(s);
}
public Page getActivePage() {
return activePage;
}
public boolean setActivePage(String activePage) {
Page p = this.libro.get(activePage);
this.nameActivePage = activePage;
this.activePage = p;
return true;
}
public String getNameActivePage(){
return nameActivePage;
}
public boolean containsPage(String s){
return libro.containsKey(s);
}
public HashMap<String, Page> getLibro() {
return this.libro;
}
}
Thank you.
Okey I think I resolved correctly I just made some changes in "Cargar":
try {
String ruta = comando.substring(8, comando.length()-1).trim();
FileInputStream fileIn = new FileInputStream(ruta);
ObjectInputStream in = new ObjectInputStream(fileIn);
Book libro_c = (Book) in.readObject();
libro.setLibro(libro_c.getLibro());
in.close();
fileIn.close();
Now it works! Thanks for your help!!
I am trying to edit an array of objects after reading them by using Serializable.
The code works fine for new instance of my object but gives a NullPointer exception when I try to edit the object read from file.
public class ShoppingCenter implements Serializable{
// I cant write to file without transient
transient Scanner scan=new Scanner (System.in);
private static final long serialVersionUID = 6529685098267757692L;
//This is the edit details method which will be used to modify the details
public void editDetails()
{
System.out.println("The details are as follows:");
System.out.println("*Name is "+ name);
System.out.println("\t(1-Edit 2-Continue)");
// *******This is where it gives the exception********
if (scan.nextInt()==1)
{System.out.println("\t Write the new value..");
name=scan.next();
System.out.println("Done..");}
System.out.println("*Location is "+ location);
System.out.println("\t(1-Edit 2-Continue)");
if (scan.nextInt()==1)
{System.out.println("\t Write the new value..");
location=scan.next();
System.out.println("Done..");}
}
This is the stack Trace.
java.lang.NullPointerException
at ShoppingCenter.editDetails(ShoppingCenter.java:40)
at Part3Main.searchObject(Part3Main.java:99)
at Part3Main.init(Part3Main.java:130)
at Part3Main.main(Part3Main.java:189)
Here is my driver.
public void init(){
readFile("shoppingCenter");
}
public void readFile(String name){
try{
FileInputStream fis = new FileInputStream(name);
ObjectInputStream ois = new ObjectInputStream(fis);
sc = (ShoppingCenter[]) ois.readObject();
ois.close();
System.out.println("The Object was succesfully read from the file");
//System.out.println(sc[1].toString());
//System.out.println(sc.toString());
}
catch (Exception ex){
ex.printStackTrace();
}
}
A little help would be really appreciated.. Thanks ..
I have to write a different class to read a file of different kind. Now project is deployed on client side. And we have to give support to new files. so we have to create a new class and also modify in service class to create a new object of newly added class. Writing a new class for new type of class is fine. But I do not want to change service class each time. Is there any solution for this kind of problem? Thanks in advance.
Update 1: here is code of service class
#Service("StockistServiceImpl")
public class StockistServiceImpl implements StockistService {
#Override
#Transactional(propagation = Propagation.REQUIRED,rollbackFor=Exception.class)
public JSONArray saveStockistOrder(Integer stockistId,
MultipartFile[] orderFile, String orderNumber, String orderDate,
String partyCode,String order,Integer userId)
{
List<Pair<String, Integer>> charList = new ArrayList<Pair<String, Integer>>();
Properties code1 = new Properties();
try {
code.load(StockistServiceImpl.class.getClassLoader().getResourceAsStream("categoryOfFile.properties"));
}
catch (IOException e) {
//System.out.println("error in loading divisionNamePdfCode.properties");
e.printStackTrace();
}
String readDuelListedTxtFile = code.getProperty("readDuelListedTxtFile");
String readStartLineLengthForOrderTxtFile = code.getProperty("readStartLineLengthForOrderTxtFile");
String ReadFileWithNoStartLineTxtFile = code.getProperty("ReadFileWithNoStartLineTxtFile");
String ReadStartLineLengthForQtySingleListTxtFile = code.getProperty("ReadStartLineLengthForQtySingleListTxtFile");
if (readDuelListedTxtFile.contains(partyCode
.trim())) {
charList.addAll(dualListText
.readDuelListedTxtFile(
fileName, codeDetails));
}
else if (readStartLineLengthForOrderTxtFile.contains(partyCode
.trim())) {
charList.addAll(lineLength
.readStartLineLengthForOrderTxtFile(
fileName, codeDetails));
}
else if (ReadFileWithNoStartLineTxtFile.contains(partyCode
.trim())) {
T_FileWithNoStartLine noStartLine = new T_FileWithNoStartLine();
charList.addAll(noStartLine
.readFileWithNoStartLineTxtFile(
fileName, codeDetails));
}
else if (ReadStartLineLengthForQtySingleListTxtFile.contains(partyCode
.trim())) {
T_StartLineLengthForQtySingleList noStartLine = new T_StartLineLengthForQtySingleList();
charList.addAll(noStartLine
.readStartLineLengthForQtySingleListTxtFile(
fileName, codeDetails));
}
}
Update 2: here is property file from where we know that what is file type for a stockist.
#fileType,stockistCode
fileType1=ST001,ST009
fileType2=ST002,ST005,ST006
fileType3=ST003,ST007
fileType4=ST004,ST008
and i want to add a new property file like this to map a file type with class name so if a new class is added and then we will not have to edit service class.
#fileType,fullyqualifiedclassName
fileType1=FullyQualifiedClassName1
fileType2=FullyQualifiedclassName2
fileType3=FullyQualifiedClassName3
fileType4=FullyQualifiedclassName4
Separate the creation of the file readers objects and the service class.
public class BuildFileReader() {
FileReader getReader(String xyz) {
FileReader reader;
...
your logic
reader = new WhatEverReaderYouWant();
...
return reader;
}
}
The service class simply asks the BuildFileReader which FileReader to use and doesn't need to change anymore.
public class StockistServiceImpl {
...
BuildFileReader bfr = new BuildFileReader();
FileReader fileReader = bfr.getReader(xyz);
fileReader.readFile(fileName, codeDetails);
...
}
If you need only one type of file reader per client, you could configure your BuildFileReader for each client.
If you need more than one type of file reader per client, define an interface for each type an add a getReaderXYZ() function for each needed type in BuildFileReader.
Instance can be created at runtime using reflection in java, please have a look at below post:
Creating an instance using the class name and calling constructor
Finally after doing some code changes and adding property file for mapping class names with property of file here is the code and working fine.
#Service("StockistServiceImpl")
public class StockistServiceImpl implements StockistService {
List<Pair<String, Integer>> charList = new ArrayList<Pair<String, Integer>>();
Map<String,String> mapTxtFile = new HashMap<String, String>();
Properties fileTypeProperties = new Properties();
Properties matchClassNameProperties = new Properties();
try {
fileTypeProperties.load(StockistServiceImpl.class.getClassLoader().getResourceAsStream("fileTypeProperties.properties"));
}
catch (IOException e) {
//e.printStackTrace();
}
try {
matchClassNameProperties.load(StockistServiceImpl.class.getClassLoader().getResourceAsStream("matchClassNameProperties.properties"));
}
catch (IOException e) {
//e.printStackTrace();
}
for (String key : fileTypeProperties.stringPropertyNames()) {
String value = fileTypeProperties.getProperty(key);
mapTxtFile.put(key, value);
if(value.contains(partyCode.trim())){
String className = matchClassNameProperties.getProperty(key);
try {
Class clazz = Class.forName(className);
try {
TxtFile objToReadTxtFile = (TxtFile) clazz.newInstance();
charList= objToReadTxtFile.readTxtFile(fileName, codeDetails);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
//read normally else block
}
}
}
Now it is working fine.But for that i created an interface for reading txt file which has readTxtFile method. and all other classes now implement this interface.
I've reasearched a lot of websites and I couldn't find answear. I'm trying to write to .txt file my ArrayList which constains class objects. Every time I try to do it I`m getting exception. With reading is the same problem. Here is my code:
public static void write()
{
try
{
FileOutputStream out = new FileOutputStream("clients.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);
oout.writeObject(lista);
oout.close();
}
catch(Exception ioe)
{
System.out.println("writing Error!");
welcome();
}
}
public static void read()
{
try
{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("clients.txt"));
lista = (List<Client>) ois.readObject();
}
catch (ClassNotFoundException ex)
{
System.out.println("Koniec pliku");
}
catch(IOException ioe)
{
System.out.println("Error!");
welcome();
}
}
I guess you're looking for the Serializable interface of Java. In order to save objects you're class have to implement it.
The question is: What execatly do you want to save? The content of the list so that you can save it in a file and load it afterwards?
This simple example works for me (for the scenario I mention above):
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public User(String name, int ag) {
this.name = name;
this.age = age;
}
#Override
public String toString() {
return (this.name + ' ' + this.age);
}
}
public class Main {
private static List<User> l;
public static void main(String[] args) {
l = new ArrayList<User>();
user1 = new User("John", 22);
user2 = new User("Jo", 33);
l.add(user1);
l.add(user2);
write();
}
public static void write() {
try {
FileOutputStream fos = new FileOutputStream("testout.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(l);
oos.close();
} catch (Exception ioe) {
System.out.println("writing Error!");
}
}
}
Ok I have changed a bit (not each function just the read and write functionality) and this work.
Link to Code.
One important thing is that the Scanner class is not serializable. Therefore, you have to make it static for example.