Is there a reliable way to convert any object to a String and then back again to the same Object? I've seen some examples of people converting them using toString() and then passing that value into a constructor to reconstruct the object again but not all objects have a constructor like this so that method wont work for all cases. What way will?
Yes, it is called serialization!
String serializedObject = "";
// serialize the object
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(myObject);
so.flush();
serializedObject = bo.toString();
} catch (Exception e) {
System.out.println(e);
}
// deserialize the object
try {
byte b[] = serializedObject.getBytes();
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
MyObject obj = (MyObject) si.readObject();
} catch (Exception e) {
System.out.println(e);
}
This is the code:
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(stringList);
so.flush();
redisString = new String(Base64.encode(bo.toByteArray()));
}
catch (Exception e) {
e.printStackTrace();
}
try {
byte b[] = Base64.decode(redisString.getBytes());
ByteArrayInputStream bi = new ByteArrayInputStream(b);
ObjectInputStream si = new ObjectInputStream(bi);
List<String> stringList2 = (List<String>)si.readObject();
System.out.println(stringList2.get(1));
}
catch (Exception e) {
e.printStackTrace();
}
Serialize to byte array, convert to Base64. Then decode Base64 back to byte array and deserialize.
None will work in all cases. An object may, e.g., contain references to other JVMs handling their state, and this state may be not available for you to restore.
Additional problems you're going to meet will include open streams, listening sockets, and almost anything else from the outer world.
There's no need to repeat that most at least two of Java core engineers say that serialization was one of the greatest mistakes a single worst feature in Java, that is, after finalization. (I do love serialization nevertheless, it's handy. But it won't always work.)
One way is to use JSON. For implementation specific in Java, the answer might be given in this post:
java code corresponding to Newtonsoft.Json.JsonConvert.SerializeObject(Object source,Newtonsoft.Json.JsonSerializerSettings()) in .net?
Using JSON is reliable enough that it's used for web application development (Ajax).
Yes, it is Serialization You can use, ObjectInputStream.readObject and ObjectOutputStream.writeObject. Please see below example:
MyClass myClass = new MyClass();
FileOutputStream fileStream = new FileOutputStream("myObjectFile.txt");
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(os);
os.close();
FileInputStream fileInStream = new FileInputStream("myObjectFile.txt");
ObjectInputStream ois = new ObjectInputStream(fileInStream);
MyClass myClass2 = ois.readObject();
ois.close();
You can use SerializationUtils from org.apache.commons.
It provides the methods serialize and deserialize
Related
I have pretty large number of classes which are Serializable/Externalizable and unfortunately it happens quite often that I forget to serailize/desirialize a new field when adding it to a class or mispell readObject instead of readDouble. So I decided to write some sort of unit test which is ignored and won't run by maven-surefire-plugin. It's only for my own needs. It looks like this:
#Test(enabled = false)
public void testEquality(Object o){
String oPart = o.toString();
try (FileOutputStream fos = new FileOutputStream("/home/myusr/testser/" + oPart);
ObjectOutputStream ous = new ObjectOutputStream(fos)) {
ous.writeObject(o);
} catch (FileNotFoundException | IOException e) {
e.printStackTrace();
}
Object oo = null;
try (FileInputStream fis = new FileInputStream("/home/myusr/testser/" + oPart);
ObjectInputStream ois = new ObjectInputStream(fis)) {
Object oo = ois.readObject();
} catch (FileNotFoundException | IOException | ClassNotFoundException e) {
e.printStackTrace();
}
// Need to compare all non-transient fields of o and oo
}
But the question is how to compare all fields which are not transient with the same name. I would not want to override equals method just for testing purpose.
Is there a way to deal with it? Maybe there are some commons/guava libraries which can cope with that.
You can use reflection to do it starting with YourClaas.class.getDeclaredFields(). Then you have to filter the returned fields, retrieve the values from the objects and do the comparison.
What's the best way to copy one Java object of a class to another object of the same class? I tried BeanUtil.copyProperties but it didn't work for some reason. The class is a complex class. (class contains another class objects etc)
My aim is to populate values in order through hibernate function
Public Response getOrder(Order order, Ticket ticket) {
order = OrderManager.getOrderByTicket(ticket); //Hibernate function This doesn't work, order object gets a new reference
}
Tried doing this
Public Response getOrder(Order order, Ticket ticket) {
Order temp = OrderManager.getOrderbByTicket(ticket);
//Now I want to copy temp to order
}
To do a deep copy using Serialize / DeSerialize, you can use the code like below,
public Object deepCopy(Object input) {
Object output = null;
try {
// Writes the object
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(input);
// Reads the object
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
output = objectInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return output;
}
If all the fields are serializable then you can use ObjectOutputStream and ObjectInputStream.
If You need special handling during the serialization and deserialization process then implement special methods writeObject() and readObject().
Please have a look at IO: Custom Reading and Writing with Serializable .
Sample code:
class MyClass implements Serializable {
private static final long serialVersionUID = 1L;
String str;
List<Integer> list = new ArrayList<Integer>();
public MyClass(String str) {
this.str = str;
}
}
MyClass obj1 = new MyClass("abc");
obj1.list.add(1);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(buffer);
oos.writeObject(obj1);
oos.close();
byte[] rawData = buffer.toByteArray();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(rawData));
MyClass obj2 = (MyClass) ois.readObject();
System.out.println(obj2.str);
System.out.println(obj2.list.get(0));
I suppose you could use reflection if it was REALLY important or time consuming, but as I see it, there are two main choices
One
If you have access to the class, just implement Clonable and have the clone method produce a deep copy of the object and all its subobjects.
Two
Code it by hand. It may be time consuming and boring, but it works in all cases.
I believe you are talking about a 'deep' copy.
A similar question and various solutions are detailed here:
How do you make a deep copy of an object in Java?
The easiest way seems to be serialising the object and then deserialising it.
Better do it like this:
Public Response getOrder(Request request) {
Order temp = OrderManager.getOrderbByTicket(request.getTicket());
request.setOrder(temp);
//process the response
}
This will solve the problem of getting back the Order to the caller of the function. If you want that the caller gets a deep copy than serialize and deserialize it before seting it to the request
My teacher said that in file server program ObjectInputStreamReader is compulsory to write. When I asked the reason then he said me it is comfortable for file server program. I am thinking that it is not necessary reason. Why InputStreamReader or other alternatives can not be used? what is the advantage of ObjectInputStreamReader over InputStreamReader.
Here code for client/server:
public class Client {
public static void main(String[] args) {
Socket s = null;
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
Scanner sc = new Scanner(System.in);
String data = "";
try {
s = new Socket("localhost", 1234);
System.out.println("client is connectd");
ois = new ObjectInputStream(s.getInputStream());
String jai = (String) ois.readObject();
System.out.println("DATA from SERVER:" + jai);
oos = new ObjectOutputStream(s.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Enter file name:");
try {
String fil = (String) sc.next();
OutputStream pw = new FileOutputStream(fil + ".new");
oos.writeObject(fil);
data = (String) ois.readObject();
pw.write(data.getBytes());
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("Content of file:" + data);
}
}
Can any one say what is actual reason ?
I think you mean ObjectInputStream and BufferedInputStream (not readers).
ObjectInputStream wraps input stream and provides typed methods that allow reading data of certain type from the stream. For example readDouble(), readObject() etc.
BufferedInputStream does not provide additional API (comparing to regular InputStream). The only thing it does is buffering of data, i.e. it reads data chunk-by-chunk that is much more efficient way than reading byte-by-byte.
An InputStream is an abstract class that can be used to define any type of input stream, including reading from file systems, URLs, sockets, etc.
You don't actually create an InputStream, as it doesn't mean anything by itself. Rather, you create a type of InputStream that defines how to read/write a particular type of data, such as the suggested ObjectInputStream. This class defines that the data being written is a Java Object (that implements Serializable or Externalizable). There are other InputStreams that are used for generic file data, images, audio, and a whole range of other types.
There is no such thing as an ObjectInputStreamReader, unless you write a class like this yourself that has the purpose of writing to an ObjectInputStream.
Refer to the ObjectInputStream and InputStream Java docs for more enlightenment
So I am using a proprietary java library in a project which I don't have access to source code.
It throws a Message object, and obviously I can't implement Serializable. It's generated throughout runtime.
what are my options? Is there a way to serialize the Message object into a byte array and back into the object?
UPDATE: I was able to serialize the object to JSON (http://code.google.com/p/json-io/) but couldn't convert it back to an object as it returns null. So I am trying to convert it to byte array using the code below. Still not working.
public byte[] toByteArray (Object obj)
{
byte[] bytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
oos.close();
bos.close();
bytes = bos.toByteArray ();
}
catch (IOException ex) {
//TODO: Handle the exception
}
return bytes;
}
public Object toObject (byte[] bytes)
{
Object obj = null;
try {
ByteArrayInputStream bis = new ByteArrayInputStream (bytes);
ObjectInputStream ois = new ObjectInputStream (bis);
obj = ois.readObject();
}
catch (IOException ex) {
//TODO: Handle the exception
}
catch (ClassNotFoundException ex) {
//TODO: Handle the exception
}
return obj;
}
You could write a wrapper that is serializable and stores everything you need to recreate the Message object.
XStream is one way to go.
Sure, you just can't use the java.lang.Serializable mechanism.
Choose any format: XML, JSON, protocol buffer, or something else that might work for you.
Now you're responsible for both ends of the conversation: serialization and deserialization.
If the object is a Java bean, you can use java.beans.XMLEncoder and java.beans.XMLDecoder for serialization.
I have class which is seralized and does convert a very large amount of data object to blob to save it to database.In the same class there is decode method to convert blob to the actual object.Following is the code for encode and decode of the object.
private byte[] encode(ScheduledReport schedSTDReport)
{
byte[] bytes = null;
try
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(schedSTDReport);
oos.flush();
oos.close();
bos.close();
//byte [] data = bos.toByteArray();
//ByteArrayOutputStream baos = new ByteArrayOutputStream();
//GZIPOutputStream out = new GZIPOutputStream(baos);
//XMLEncoder encoder = new XMLEncoder(out);
//encoder.writeObject(schedSTDReport);
//encoder.close();
bytes = bos.toByteArray();
//GZIPOutputStream out = new GZIPOutputStream(bos);
//out.write(bytes);
//bytes = bos.toByteArray();
}
catch (Exception e)
{
_log.error("Exception caught while encoding/zipping Scheduled STDReport", e);
}
decode(bytes);
return bytes;
}
/*
* Decode the report definition blob back to the
* ScheduledReport object.
*/
private ScheduledReport decode(byte[] bytes)
{
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ScheduledReport sSTDR = null;
try
{
ObjectInputStream ois = new ObjectInputStream(bais);
//GZIPInputStream in = new GZIPInputStream(bais);
//XMLDecoder decoder = new XMLDecoder(in);
sSTDR = (ScheduledReport)ois.readObject();//decoder.readObject();
//decoder.close();
}
catch (Exception e)
{
_log.error("IOException caught while decoding/unzipping Scheduled STDReport", e);
}
return sSTDR;
}
The problem here is whenver I change something else in this class
means any other method,a new class version is created and so the new version the class is unable to decode the originally encoded blob object. The object which I am passing for encode is also seralized object but this problem exists. Any ideas thanks
Yup, Java binary serialization is pretty brittle :(
You can add a static serialVersionUID field to the class so that you can control the version numbers... this should prevent problems due to adding methods. You'll still run into potential issues when fields are added though. See the JavaDocs for Serializable for some more details.
You might want to consider using another serialization format such as Protocol Buffers to give you more control though.
You can implement java.io.Externalizable so that you are able to control what is serialized and expected in deserialization.