Let's say I have a serializable class AppMessage
.
I would like to transmit it as byte[]
over sockets to another machine where it is rebuilt from the bytes received.
How could I achieve this?
Let's say I have a serializable class AppMessage
.
I would like to transmit it as byte[]
over sockets to another machine where it is rebuilt from the bytes received.
How could I achieve this?
Prepare the byte array to send:
static byte[] serialize(final Object obj) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream out = new ObjectOutputStream(bos)) {
out.writeObject(obj);
out.flush();
return bos.toByteArray();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
Create an object from a byte array:
static Object deserialize(byte[] bytes) {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
try (ObjectInput in = new ObjectInputStream(bis)) {
return in.readObject();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
ObjectInput
, ObjectOuput
, ByteArrayOutputStream
and ByteArrayInputStream
all implement the AutoCloseable
interface, wouldn't it be good practice to use it to avoid missing closing them by mistake? (I'm not entirely sure if this is the best practice, that's why I'm wondering.) Example: try(ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)){ /*Do stuff*/ }catch(IOException e){/*suppress exception*/}
. It also removes the need for the final
clause and its additional try-catch
. –
Lemieux The best way to do it is to use SerializationUtils
from Apache Commons Lang.
To serialize:
byte[] data = SerializationUtils.serialize(yourObject);
To deserialize:
YourObject yourObject = SerializationUtils.deserialize(data)
As mentioned, this requires Commons Lang library. It can be imported using Gradle:
compile 'org.apache.commons:commons-lang3:3.5'
Maven:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
And more ways mentioned here
Alternatively, the whole collection can be imported. Refer this link
SerializationUtils.serialize(o)
, your object need this implements Serializable
–
Omnipresent If you use Java >= 7, you could improve the accepted solution using try with resources:
private byte[] convertToBytes(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos)) {
out.writeObject(object);
return bos.toByteArray();
}
}
And the other way around:
private Object convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream in = new ObjectInputStream(bis)) {
return in.readObject();
}
}
toByteArray()
is invoked, i.e. it could happen that some data remains in internal buffers and that not all data is transferred to the returned byte[] array. I have not found a specification of the ObjectOutputStream which describe buffer behavior. –
Bissau Can be done by SerializationUtils, by serialize & deserialize method by ApacheUtils to convert object to byte[] and vice-versa , as stated in @uris answer.
To convert an object to byte[] by serializing:
byte[] data = SerializationUtils.serialize(object);
To convert byte[] to object by deserializing::
Object object = (Object) SerializationUtils.deserialize(byte[] data)
Click on the link to Download org-apache-commons-lang.jar
Integrate .jar file by clicking:
FileName -> Open Medule Settings -> Select your module -> Dependencies -> Add Jar file and you are done.
Hope this helps.
Another interesting method is from com.fasterxml.jackson.databind.ObjectMapper
byte[] data = new ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)
Maven Dependency
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
I also recommend to use SerializationUtils tool. I want to make a ajust on a wrong comment by @Abilash. The SerializationUtils.serialize()
method is not restricted to 1024 bytes, contrary to another answer here.
public static byte[] serialize(Object object) {
if (object == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.flush();
}
catch (IOException ex) {
throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
}
return baos.toByteArray();
}
At first sight, you may think that new ByteArrayOutputStream(1024)
will only allow a fixed size. But if you take a close look at the ByteArrayOutputStream
, you will figure out the the stream will grow if necessary:
This class implements an output stream in which the data is written into a byte array. The buffer automatically grows as data is written to it. The data can be retrieved using
toByteArray()
andtoString()
.
If you are using spring, there's a util class available in spring-core. You can simply do
import org.springframework.util.SerializationUtils;
byte[] bytes = SerializationUtils.serialize(anyObject);
Object object = SerializationUtils.deserialize(bytes);
I would like to transmit it as byte[] over sockets to another machine
// When you connect
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
// When you want to send it
oos.writeObject(appMessage);
where it is rebuilt from the bytes received.
// When you connect
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
// When you want to receive it
AppMessage appMessage = (AppMessage)ois.readObject();
Spring Framework org.springframework.util.SerializationUtils
byte[] data = SerializationUtils.serialize(obj);
In case you want a nice no dependencies copy-paste solution. Grab the code below.
MyObject myObject = ...
byte[] bytes = SerializeUtils.serialize(myObject);
myObject = SerializeUtils.deserialize(bytes);
import java.io.*;
public class SerializeUtils {
public static byte[] serialize(Serializable value) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try(ObjectOutputStream outputStream = new ObjectOutputStream(out)) {
outputStream.writeObject(value);
}
return out.toByteArray();
}
public static <T extends Serializable> T deserialize(byte[] data) throws IOException, ClassNotFoundException {
try(ByteArrayInputStream bis = new ByteArrayInputStream(data)) {
//noinspection unchecked
return (T) new ObjectInputStream(bis).readObject();
}
}
}
This is just an optimized code form of the accepted answer in case anyone wants to use this in production :
public static void byteArrayOps() throws IOException, ClassNotFoundException{
String str="123";
byte[] yourBytes = null;
// Convert to byte[]
try(ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);) {
out.writeObject(str);
out.flush();
yourBytes = bos.toByteArray();
} finally {
}
// convert back to Object
try(ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
ObjectInput in = new ObjectInputStream(bis);) {
Object o = in.readObject();
} finally {
}
}
make sure to implements Serializable or exception will be your destiny
public class Dto implements Serializable {
private String firstName;
private String lastName;
private Integer myNumber;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getMyNumber() {
return myNumber;
}
public void setMyNumber(Integer myNumber) {
this.myNumber = myNumber;
}
@Override
public String toString() {
return "Dto{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", myNumber=" + myNumber +
'}';
}
}
public class Main {
public static void main(String[] args) {
Dto dto=new Dto();
dto.setFirstName("Sajjad");
dto.setLastName("ahmed");
dto.setMyNumber(0305);
byte[] serializedDto = serializeObject(dto);
System.out.println("Serialized Dto=== " + new String(serializedDto));
Dto deserializedDto = deserializeObject(serializedDto);
System.out.println("Deserialized Dto===" + deserializedDto);
}
private static byte[] serializeObject(Dto dto) {
try {
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);
objectOutputStream.writeObject(dto);
objectOutputStream.close();
byteOutputStream.close();
return byteOutputStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return null;
}}
private static Dto deserializeObject(byte[] byteArray) {
try {
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);
Dto deserializedObject = (Dto) objectInputStream.readObject();
objectInputStream.close();
byteInputStream.close();
return deserializedObject;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
code example with java 8+:
public class Person implements Serializable {
private String lastName;
private String firstName;
public Person() {
}
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "firstName: " + firstName + ", lastName: " + lastName;
}
}
public interface PersonMarshaller {
default Person fromStream(InputStream inputStream) {
try (ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
Person person= (Person) objectInputStream.readObject();
return person;
} catch (IOException | ClassNotFoundException e) {
System.err.println(e.getMessage());
return null;
}
}
default OutputStream toStream(Person person) {
try (OutputStream outputStream = new ByteArrayOutputStream()) {
ObjectOutput objectOutput = new ObjectOutputStream(outputStream);
objectOutput.writeObject(person);
objectOutput.flush();
return outputStream;
} catch (IOException e) {
System.err.println(e.getMessage());
return null;
}
}
}
© 2022 - 2024 — McMap. All rights reserved.
byte[]
? Why not just write it directly to the socket withObjectOutputStream
, and read it withObjectInputStream
? – Scoffnew ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)
– Orthogonal