Java可序列化对象到字节数组

Java可序列化对象到字节数组,java,object,serialization,Java,Object,Serialization,假设我有一个可序列化的类AppMessage 我想将它作为byte[]通过套接字传输到另一台机器,在那里它是从接收到的字节重建的 如何实现此目的?准备要发送的字节数组: ByteArrayOutputStream bos=newbytearrayoutputstream(); ObjectOutputStream out=null; 试一试{ out=新对象输出流(bos); out.writeObject(您的对象); out.flush(); byte[]yourBytes=bos.toBy

假设我有一个可序列化的类
AppMessage

我想将它作为
byte[]
通过套接字传输到另一台机器,在那里它是从接收到的字节重建的


如何实现此目的?

准备要发送的字节数组:

ByteArrayOutputStream bos=newbytearrayoutputstream();
ObjectOutputStream out=null;
试一试{
out=新对象输出流(bos);
out.writeObject(您的对象);
out.flush();
byte[]yourBytes=bos.toByteArray();
...
}最后{
试一试{
bos.close();
}捕获(IOEX异常){
//忽略关闭异常
}
}
从字节数组创建对象:

ByteArrayInputStream bis=新的ByteArrayInputStream(字节);
ObjectInput in=null;
试一试{
in=新的ObjectInputStream(bis);
对象o=in.readObject();
...
}最后{
试一试{
if(in!=null){
in.close();
}
}捕获(IOEX异常){
//忽略关闭异常
}
}

最好的方法是使用Apache中的
SerializationUtils

要序列化:

byte[] data = SerializationUtils.serialize(yourObject);
要反序列化:

YourObject yourObject = SerializationUtils.deserialize(data)

如前所述,这需要Commons Lang库。可以使用Gradle导入它:

compile 'org.apache.commons:commons-lang3:3.5'
马文:

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.5</version>
</dependency>

org.apache.commons

还有更多提到的方法


或者,可以导入整个集合。请参阅

如果使用Java>=7,则可以使用以下方法改进已接受的解决方案:

反过来说:

private Object convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
    try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
         ObjectInputStream in = new ObjectInputStream(bis)) {
        return in.readObject();
    } 
}
如@uris answer中所述,可以通过ApacheUtils的序列化和反序列化方法将对象转换为字节[],反之亦然

要通过序列化将对象转换为字节[],请执行以下操作:

byte[] data = SerializationUtils.serialize(object);
要通过反序列化将字节[]转换为对象,请执行以下操作:

Object object = (Object) SerializationUtils.deserialize(byte[] data)
点击链接到

通过单击以下内容集成.jar文件:

文件名->打开模块设置->选择您的模块->依赖项->添加Jar文件即可


希望这有帮助

我还建议使用SerializationUtils工具。我想对@Abilash的一个错误评论做一个修正。与这里的另一个答案相反,
SerializationUtils.serialize()
方法不限于1024字节

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();
}
乍一看,您可能认为
newbytearrayoutputstream(1024)
只允许固定大小。但是,如果仔细查看
ByteArrayOutputStream
,您会发现如果需要,流将增长:

这个类实现了一个输出流,其中的数据是 写入字节数组。缓冲区会随着数据的增长而自动增长 这是写给它的。 可以使用
toByteArray()
toString()

我想通过套接字将其作为字节[]传输到另一台机器

从接收到的字节中重建


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;
    }

}

}

另一个有趣的方法来自
com.fasterxml.jackson.databind.ObjectMapper

byte[]data=new ObjectMapper()。writeValueAsBytes(这里是JAVA\u OBJECT\u)

Maven依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

com.fasterxml.jackson.core
杰克逊数据绑定

springframework
org.springframework.util.SerializationUtils

byte[] data = SerializationUtils.serialize(obj);

如果您使用的是spring,SpringCore中有一个可用的util类。你可以简单地做

import org.springframework.util.SerializationUtils;

byte[] bytes = SerializationUtils.serialize(anyObject);
Object object = SerializationUtils.deserialize(bytes);

如果你想要一个好的无依赖复制粘贴解决方案。抓取下面的代码

例子 来源
import java.io.*;
公共类序列化{
公共静态字节[]序列化(可序列化值)引发IOException{
ByteArrayOutputStream out=新建ByteArrayOutputStream();
try(ObjectOutputStream outputStream=new ObjectOutputStream(out)){
outputStream.writeObject(值);
}
return out.toByteArray();
}
公共静态T反序列化(字节[]数据)引发IOException,ClassNotFoundException{
try(ByteArrayInputStream bis=新的ByteArrayInputStream(数据)){
//未检查
返回(T)新ObjectInputStream(bis).readObject();
}
}
}

这只是公认答案的优化代码形式,以防有人想在生产中使用:

    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 {

    }




}

我不是这样理解这个问题的。在我看来,他的问题似乎是如何将对象转换为字节[],而不是如何发送。泰勒:是的,你说得对。我想把这个对象转换成一个字节[]并传输它。请提供有关如何将此字节[]转换为对象的代码。请始终关闭任何流以释放系统资源。(在代码中编辑)这可以处理我无法实现可序列化的对象吗?
ObjectInput
objectOutput
ByteArrayOutputStream
ByteArrayInputStream
都实现了
自动关闭
接口,使用它来避免错误关闭它们不是一种好的做法吗?(我不完全确定这是否是最佳实践,这就是我想知道的原因。)示例:
try(ByteArrayOutputStream bos=newbytearrayoutputstream();ObjectOutput out=newobjectoutputstream(bos)){/*dostuff*/}catch(IOException e){/*抑制异常*/}
。它还消除了对
final
子句及其附加的
try-catch
的需要。是否增加了开销?最好在这一点上重建车轮。说真的,理解这一行代码和减少可能出现的错误(比如没有在正确的时间关闭流等等)要容易得多。最好的方法是使用一个提供给您的公共库:1)健壮性:人们正在使用它,因此它是有效的。2) 它只需要一行代码就可以完成上面的(最流行的答案),因此代码保持干净。3) 因为丹是这么说的。4) 关于3:-)我只是开玩笑。不幸的是,该方法将输出大小限制为1024。如果需要将文件转换为字节流,最好
byte[] data = SerializationUtils.serialize(obj);
import org.springframework.util.SerializationUtils;

byte[] bytes = SerializationUtils.serialize(anyObject);
Object object = SerializationUtils.deserialize(bytes);
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();
        }
    }
}
    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 {

    }




}