在java中从对象到字节数组再到字节数组的转换

在java中从对象到字节数组再到字节数组的转换,java,serialization,bytearray,Java,Serialization,Bytearray,我有两门课:TcpPacket和IpPacket。tcpPacket应存储在ip数据包的数据字段中。如何将tcpPacket对象可靠地转换为字节数组,以便将其存储在IpPacket的数据字段中?在另一端接收到数据包后,如何可靠地将其转换回数据包对象 public static final class TcpPacket { int source; int destination; public Packet( int source, int destination )

我有两门课:TcpPacket和IpPacket。tcpPacket应存储在ip数据包的数据字段中。如何将tcpPacket对象可靠地转换为字节数组,以便将其存储在IpPacket的数据字段中?在另一端接收到数据包后,如何可靠地将其转换回数据包对象

public static final class TcpPacket {
    int source;
    int destination;

    public Packet( int source, int destination ) {
        this.source = source;
        this.destination = destination;
    }

    public String toString() {
        return "Source: " + source + ", Dest: " + destination;
    }
}

public static final class IpPacket {
    byte[] data;

    IpPacket( byte[] data ){
        this.data = data;
    }
}

TcpPacket tcpPacket = new TcpPacket( <someint>, <someint> );

// the following doesn't work because tcppacket is not a byte array.
IpPacket ipPacket = new IpPacket( tcpPacket );
公共静态最终类TcpPacket{
int源;
int目的地;
公共数据包(int源,int目的地){
this.source=源;
this.destination=目的地;
}
公共字符串toString(){
返回“Source:+Source+”,Dest:+destination;
}
}
公共静态最终类iPacket{
字节[]数据;
IpPacket(字节[]数据){
这个数据=数据;
}
}
TcpPacket TcpPacket=新TcpPacket(,);
//由于tcppacket不是字节数组,因此以下操作不起作用。
IpPacket IpPacket=新的IpPacket(tcpPacket);
这通常是怎么做的


感谢Maricruzz

这应该可以工作,只要在从序列化/反序列化函数接收对象后将其强制转换为类即可

public static byte[] objToByte(TcpPacket tcpPacket) throws IOException {
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    ObjectOutputStream objStream = new ObjectOutputStream(byteStream);
    objStream.writeObject(tcpPacket);

    return byteStream.toByteArray();
}

public static Object byteToObj(byte[] bytes) throws IOException, ClassNotFoundException {
    ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);
    ObjectInputStream objStream = new ObjectInputStream(byteStream);

    return objStream.readObject();
}

我想为您提供手动序列化类的方法

public static final class TcpPacket {

    public byte [] toByteArray() {
        ByteBuffer b = ByteBuffer.allocate(4 * 2);
        return b.putInt(source).putInt(destination).array();
    }

    public static TcpPacket fromByteArray(byte [] bytes) {
        if (bytes.length < 8) throw new IllegalArgumentException("not enough bytes");

        ByteBuffer b = ByteBuffer.wrap(bytes);
        int source = b.getInt();
        int destination = b.getInt();
        return new TcpPacket(source, destination);
    }
}
公共静态最终类TcpPacket{
公共字节[]toByteArray(){
ByteBuffer b=ByteBuffer.allocate(4*2);
返回b.putInt(源).putInt(目标).array();
}
来自ByteArray的公共静态TcpPacket(字节[]字节){
如果(bytes.length<8)抛出新的IllegalArgumentException(“字节不足”);
ByteBuffer b=ByteBuffer.wrap(字节);
int source=b.getInt();
int destination=b.getInt();
返回新的TcpPacket(来源、目的地);
}
}
添加一个
toByteArray
和一个来自ByteArray的静态
方法可以满足您的需要,并具有以下好处:

  • 非常小的表示,只有8个字节,理论上可以用可变长度的整数编码更小
  • 不会使您的应用程序暴露于Java序列化安全问题,因为很明显,您将从网络连接反序列化数据
如果您需要序列化更复杂的数据结构,我强烈建议您选择一个完善的序列化库,例如(我个人选择的武器),或者选择一个不会遭遇Java序列化这一安全噩梦的库。

可能的重复请参阅