This thing come to my mind when I implemented custom Marker Interface. As the Serializable Marker interface is used for Serialization in java, I made my own Marker Interface to set a flag at class level.
public class MIOne implements Serializable,MarkerInterface{
private int one;
private String str;
public MIOne() {
super();
this.one = 1;
this.str = "MIOne";
}
Object writeObject() throws IOException {
if (!(this instanceof MarkerInterface)) {
FileOutputStream out = new FileOutputStream("D:\\testTransients.ser");
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(this);
} else {
System.out.println("Unable to Support Searialization");
}
return null;
}
Object readObject() throws IOException, ClassNotFoundException {
if (!(this instanceof MarkerInterface)) {
FileInputStream fis = new FileInputStream("D:\\testTransients.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
MIOne c = (MIOne) ois.readObject();
} else {
System.out.println("Unable to Support Searialization");
}
return null;
}
}
But in this I have to make a blank Interface, than implement my logic accordingly (using instanceOf operator). I need your help to sort the same problem with some other better and simpler solution. Is that possible?
Related
I'm implementing serialization, and am trying to make everything as modular as possible. When reading objects from files, I'm trying to use just one function to pass everything to an ArrayList, or something of that sort. Currently I'm doing something like this:
public static ArrayList<Class1> ReadClass1(String fileName) {
ArrayList p = null;
try {
ObjectInputStream in = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(fileName)));
p = new ArrayList<Class1>();
while (1 != 2) {
p.add((Class1) in.readObject());
}
} catch (Exception e) {
;
}
return p;
}
However, I want to read other classes, let's say Class2 or Class3, and right now I'm copy-pasting the code and just editing everything that says "Class1" to "Class2". Is there a way to pass in a specific type I want to use, like this?
public static ArrayList<myClass> ReadProducts(String fileName, myClass) { //where myClass is a class
ArrayList p = null;
try {
ObjectInputStream in = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(fileName)));
p = new ArrayList<myClass>();
while (1 != 2) {
p.add((myClass) in.readObject());
}
} catch (Exception e) {
;
}
return p;
}
So that I could reuse the function for different classes?
You can use java Generics. Please find the code below:
public static <T> ArrayList<T> ReadProducts(String fileName, Class<T> t) {
ArrayList p = null;
try {
ObjectInputStream in = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(fileName)));
p = new ArrayList<T>();
while (1 != 2) {
p.add(t.cast(in.readObject()));
}
} catch (Exception e) {
;
}
return p;
}
I have this code (sorry if I use some terms in Spanish) in Java. All is OK, until I need to write an object in a file with ObjectOutputStream, when printStackTrace says java.io.NotSerializableException.
The code is this.
package agenda;
import java.io.*;
public class Agenda implements java.io.Serializable {
public static void addContact() {
String nom, ap1, ap2, tf, em;
Contact newContact = new Contact("Nombre", "Apellido", "Apellido 2", "Telefono", "Email");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("agenda.pzs", true)) {
oos.writeObject(newContact); // NetBeans says the error is here
} catch (IOException ex) {
ex.printStackTrace(); // This is provisional only
System.out.println("OcurriĆ³ un error inesperado.");
}
}
Sorry for my bad English.
public class Agenda implements java.io.Serializable {
public static void addContact() {
String nom, ap1, ap2, tf, em;
Contact newContact = new Contact("Nombre", "Apellido", "Apellido 2", "Telefono", "Email");
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("agenda.txt",true));
oos.writeObject(newContact);
oos.close();
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("OcurriĆ³ un error inesperado.");
}
}
}
There is mistake with your bracket
and implement Serializable interface in Contact class
All objects inside Serializable class must be Serializable. this requirement is traversable - all objects below must be Serializable too..
BUT...
Assuming that Contact is a third party class or you are not allowed to modify it for any other reason, here is possible solution:
DISCLAIMER: this is tricky, if you don't know "Contact" class well it may cause many unexpected issues. You must make sure that you are able to read/write state of "Contact" class using Serializable blocks. Any change in Contact implementation must be tracked. You need a set of JUnit tests to verify if wrapper is correct.
Now get to the point:
Create ContactWrapper class that will disassemble "Contact" class to serializable class on write() and assemble this class from blocks during read(). More or less something like this:
import static org.junit.Assert.*;
import java.io.*;
import org.junit.Test;
public class Agenda {
#Test
public void addContact() throws ClassNotFoundException, FileNotFoundException, IOException {
String nom, ap1, ap2, tf, em;
Contact newContact = new Contact("Nombre", "Apellido", "Apellido 2", "Telefono", "Email");
ContactWrapper wrapper = new ContactWrapper();
wrapper.setContact(newContact);
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("agenda.pzs"));
oos.writeObject(wrapper);
} finally{
if(oos != null){
oos.close();
}
}
ObjectInputStream ois = null;
ContactWrapper wrapper_new = null;
try{
ois = new ObjectInputStream(new FileInputStream("agenda.pzs"));
wrapper_new = (ContactWrapper) ois.readObject();
} finally {
if(ois != null)
ois.close();
}
assertTrue(wrapper.equals(wrapper_new));
Contact deserializedContact = wrapper.getContact();
//Assuming that contact has corectly implemented equals()...
assertTrue(newContact.equals(deserializedContact));
}
}
================================================
import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class ContactWrapper implements Serializable{
//assume not nulls here...-->equals
private String nom, ap1, ap2, tf, em;
public ContactWrapper(){
}
public void setContact(Contact contact){
//Get State of "Contact" and write it to Serializable objects
nom = contact.getNom();
ap1 = contact.getAp1();
//etc....
}
public Contact getContact(){
//create Contact from serialized objects
return new Contact(nom, ap1, ap2, tf, em);
}
private void writeObject(java.io.ObjectOutputStream out)
throws IOException{
System.out.println("write");
out.writeObject(nom);
out.writeObject(ap1);
out.writeObject(ap2);
out.writeObject(tf);
out.writeObject(em);
}
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException{
System.out.println("read");
nom = (String) in.readObject();
ap1 = (String) in.readObject();
ap2 = (String) in.readObject();
tf = (String) in.readObject();
em = (String) in.readObject();
}
private void readObjectNoData()
throws ObjectStreamException{
System.out.println("readNoData");
//set everything to null?
}
#Override
public boolean equals(Object other) {
if(this == other) return true;
if(other instanceof ContactWrapper){
ContactWrapper that = (ContactWrapper)other;
if(this.nom.equals(that.nom) &&
this.ap1.equals(that.ap1)
//...etc etc
){
return true;
}
}
return false;
}
}
Edit:
Source: http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
Ok so i have two classes: Content and TrackUserChanges . They have the same fields.
public class Content{
private Long id;
......
private SortedSet<Content> children = new TreeSet<Content>();
}
public class TrackUserChanges{
private Long id;
.....
private SortedSet<Content> children = new TreeSet<Content>();
}
I want to clone the data from Content to TrackUserChanges:
I have the children from an instance of content:
SortedSet<Content> children = content.getChildren();
This can contain many other contents, and that contents can have also children, etc.
SortedSet<TrackUserChanges> children1 = convertContentSetToTrackUserChangesSet(children);
This is the method:
public SortedSet<TrackUserChanges> convertContentSetToTrackUserChangesSet(SortedSet<Content> children){
SortedSet<TrackUserChanges> children1 = new TreeSet<TrackUserChanges>();
for(Content c : children){
TrackUserChanges trackU = new TrackUserChanges();
trackU.setCategory(c.getCategory());
trackU.setId(c.getId());
trackU.setBook(c.getBook());
trackU.setInsertUser(c.getInsertUser());
trackU.setParent(c.getParent());
trackU.setParentId(c.getParentId());
trackU.setRelativeSortOrder(c.getRelativeSortOrder());
trackU.setText(c.getText());
trackU.setType(c.getType());
children1.add(trackU);
}
return children1;
}
I need somehow to call recusively or something like that... and I can't do trackU.setChildren(c.getChildren()) because the types don't match :/
#Mifmif
try {
FileOutputStream fout = new FileOutputStream("a.dat");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(content);
oos.close();
}
catch (Exception e) { e.printStackTrace(); }
TrackUserChanges trackUserChanges11 = new TrackUserChanges();
try {
FileInputStream fin = new FileInputStream("a.dat");
MyCustomObjectInputStream custom = new MyCustomObjectInputStream(fin);
// custom.readClassDescriptor();
trackUserChanges11 = (TrackUserChanges) custom.readObject();
System.out.println("IDDDDD" + trackUserChanges11.getId());
custom.close();
}
catch (Exception e) { e.printStackTrace(); }
ClassCastException :)
If you have two classes with identical properties that have identical behaviour, separate those fields/behaviour into a separate class and extend that class in your other classes. This should allow you to copy directly between them.
Make your class implements Cloneable. Then just call the function clone of the SortedSet.
http://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html
Here is a solution based on serialization , make both of your class serializable and if you want to go from one class instance to another, serialize your instance into a file , and read it using MyCustomObjectInputStream :
class MyCustomObjectInputStream extends ObjectInputStream {
public MyCustomObjectInputStream(InputStream in) throws IOException {
super(in);
}
#Override
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();
if (resultClassDescriptor.getName().equals("name.of.the.package.OldClassName"))
resultClassDescriptor = ObjectStreamClass.lookup(name.of.the.package.NewClassName.class);
return resultClassDescriptor;
}
}
I resolved the problem
public TrackUserChanges convertContentToTrack(Content c) {
TrackUserChanges t = new TrackUserChanges();
t.setCategory(c.getCategory());
t.setId(c.getId());
t.setBook(c.getBook());
t.setInsertUser(c.getInsertUser());
t.setParent(c.getParent());
t.setParentId(c.getParentId());
t.setRelativeSortOrder(c.getRelativeSortOrder());
t.setText(c.getText());
t.setType(c.getType());
if (c.getChildren().size() == 0) {
return t;
}
SortedSet<TrackUserChanges> childs = new TreeSet<TrackUserChanges>();
for (Content content : c.getChildren()) {
childs.add(convertContentToTrack(content));
}
t.setChildren(childs);
return t;
}
Thanks anyway :)
i'm new to file i/o so i'm sorry if this is a pretty bad question.
Currently I have an add method/main method and a person class my outputstream is working fine in the add method: This is at the top of the method
FileOutputStream myFile = null;
try {
myFile = new FileOutputStream("txt123.txt");
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(myFile);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
And I then have this twice because there are two types of people that can be added
oos.writeObject(person);
oos.close();
System.out.println("Done");
So my question, how do i get the input working and finally where do i put it, in the add method or the main method, I read how to do what i done here: http://www.mkyong.com/java/how-to-write-an-object-to-file-in-java/
He also has a guide on reading in the objects but I cant seem to get it working
Thanks!
You would be reading the file you just created like this:
ObjectInputStream in =
new ObjectInputStream(new FileInputStream("txt123.txt"));
// terrible file name, because this is binary data, not text
try{
Person person = (Person) in.readObject();
finally{
in.close();
}
You can combine the ObjectOutputStream with the FileOutputStream as follows. I'm also guessing you need to place the read/write code in one place to allow re-use. Here's a simple example with the read/write in a DAO.
public static class Person implements Serializable {
private String name;
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
}
public static class PersonDao {
public void write(Person person, File file) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(file));
oos.writeObject(person);
oos.close();
}
public Person read(File file) throws IOException,
ClassNotFoundException {
ObjectInputStream oos = new ObjectInputStream(new FileInputStream(
file));
Person returnValue = (Person) oos.readObject();
oos.close();
return returnValue;
}
}
public static void main(String[] args) throws IOException,
ClassNotFoundException {
PersonDao personDao = new PersonDao();
Person alice = new Person("alice");
personDao.write(alice, new File("alice.bin"));
Person bob = new Person("bob");
personDao.write(bob, new File("bob.bin"));
System.out.println(personDao.read(new File("alice.bin")));
System.out.println(personDao.read(new File("bob.bin")));
}
I want to store an object from my class in file, and after that to be able to load the object from this file. But somewhere I am making a mistake(s) and cannot figure out where. May I receive some help?
public class GameManagerSystem implements GameManager, Serializable {
private static final long serialVersionUID = -5966618586666474164L;
HashMap<Game, GameStatus> games;
HashMap<Ticket, ArrayList<Object>> baggage;
HashSet<Ticket> bookedTickets;
Place place;
public GameManagerSystem(Place place) {
super();
this.games = new HashMap<Game, GameStatus>();
this.baggage = new HashMap<Ticket, ArrayList<Object>>();
this.bookedTickets = new HashSet<Ticket>();
this.place = place;
}
public static GameManager createManagerSystem(Game at) {
return new GameManagerSystem(at);
}
public boolean store(File f) {
try {
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(games);
oos.writeObject(bookedTickets);
oos.writeObject(baggage);
oos.close();
fos.close();
} catch (IOException ex) {
return false;
}
return true;
}
public boolean load(File f) {
try {
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
this.games = (HashMap<Game,GameStatus>)ois.readObject();
this.bookedTickets = (HashSet<Ticket>)ois.readObject();
this.baggage = (HashMap<Ticket,ArrayList<Object>>)ois.readObject();
ois.close();
fis.close();
} catch (IOException e) {
return false;
} catch (ClassNotFoundException e) {
return false;
}
return true;
}
.
.
.
}
public class JUnitDemo {
GameManager manager;
#Before
public void setUp() {
manager = GameManagerSystem.createManagerSystem(Place.ENG);
}
#Test
public void testStore() {
Game g = new Game(new Date(), Teams.LIONS, Teams.SHARKS);
manager.registerGame(g);
File file = new File("file.ser");
assertTrue(airport.store(file));
}
}
The solution of this problem is that when you are using other objects, let say class A, into a collection like HashMap and want to serialize the HashMap object, then implement the interface Serializable for class A like this:
class A implements Serializable {
}
...
HashMap<Integer,A> hmap;
...
Otherwise that object will not be serializable.
I hope it will solve this problem now.
Try oos.flush() before you close it.
Please remenber that the whole object graph is persisted during serialize. If you have some references to GUI classes for example, you either have to make them serializable, too, or tag them as "transient", so Java won't serialize them.