您的位置:

从多个方面详细阐述object转byte数组

一、为什么需要将object转化为byte数组

在数据的传输和存储过程中,我们常常需要将对象转化为byte数组。这主要是因为在网络传输、磁盘存储、对象序列化等场景中,byte数组具有以下几个优点:

1、在各种机器和系统之间传输数据的唯一通用方式就是将数据转换成byte数组

2、byte数组在JAVA和.NET等主流编程语言中被广泛的使用

3、更加灵活处理数据

示例代码:

public static byte[] objectToByteArray(Object obj) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(out);
    os.writeObject(obj);
    return out.toByteArray();
}

二、如何实现object转byte数组

实现将object转化为byte数组的方法基本上分为两个方案:

1、使用Java序列化机制,将目标对象序列化为byte数组

2、手工编写二进制转换工具类,将目标对象按照特定的顺序转换为byte数组

使用第一个方案的好处是,无需考虑数据存储结构和数据类型,因为Java序列化机制会自动处理这些问题。

另一方面,由于Java序列化机制是重量级的,一些对象序列化时会存在性能问题,例如大量的计算和IO连续读写。

示例代码:

public static byte[] serialize(Object obj) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(obj);
    return bos.toByteArray();
}

三、如何反序列化byte数组为object

如果要将byte数组转换回对象,必须将byte数组还原为原始的Java对象。

示例代码:

public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
    ObjectInputStream ois = new ObjectInputStream(bis);
    return ois.readObject();
}

四、如何处理非序列化对象

在某些情况下,对象可能无法进行Java序列化,此时可以使用手工编写的转换工具类将对象转换为byte数组。

示例代码:

public static byte[] toByteArray(String s) {
    try {
        byte[] data = s.getBytes("ISO-8859-1");
        int len = data.length;
        byte[] out = new byte[len];
        for (int i = 0; i < len; i++) {
            out[i] = data[i];
        }
        return out;
    } catch (UnsupportedEncodingException e) {
        return null;
    }
}

五、如何处理序列化对象中的特殊情况

在某些情况下,序列化对象可能会遇到一些特殊情况,例如:

1、序列化的对象含有敏感信息,需要忽略这部分信息

2、序列化时出现循环应用,需要正常转换

示例代码:

public class CustomObjectOutputStream extends ObjectOutputStream {
    public CustomObjectOutputStream(OutputStream out) throws IOException {
        super(out);
    }
 
    @Override
    protected void writeStreamHeader() throws IOException {
        return;
    }
 
    @Override
    protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException {
        return;
    }
}

六、遇到byte数组转object卡顿咋办

当byte数组非常大时,将byte数组转化为object可能会非常耗时。

一种简单的解决方法是,将byte数组分割成多个部分,然后逐步转换为不同的object。

示例代码:

public static List<Object> splitArray(Object[] array, int chunkSize) {
    List<Object> listOfArrays = new ArrayList<Object>();
    int totalSize = array.length;
    int offset = 0;
    while (totalSize > 0) {
        int length = Math.min(totalSize, chunkSize);
        Object subArray = Array.newInstance(array.getClass().getComponentType(), length);
        System.arraycopy(array, offset, subArray, 0, length);
        offset += length;
        totalSize -= length;
        listOfArrays.add(subArray);
    }
    return listOfArrays;
}

七、如何进行序列化和反序列化的性能测试

如何进行Java序列化和反序列化的性能测试?目前最常用的是使用jmh测试框架:JMH 是用于基准测试的 Java Microbenchmark Harness,是 OpenJDK 工具集的一部分,提供了简单而强大的基准测试方法。它的使用方式类似JUnit,基于注解构建并运行测试。

示例代码:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, jvmArgs = {"-Xms2G", "-Xmx2G"})
@Warmup(iterations = 3)
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
public class SerializationTest {
 
    private static final byte[] DATA = createData();
    private static final Serializable OBJECT = new MyObject();
 
    private static byte[] createData() {
        Random random = new Random();
        byte[] data = new byte[1024 * 1024];
        random.nextBytes(data);
        return data;
    }
 
    @Benchmark
    public byte[] serialize() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(OBJECT);
        return bos.toByteArray();
    }
 
    @Benchmark
    public Object deserialize() throws IOException, ClassNotFoundException {
        ByteArrayInputStream bis = new ByteArrayInputStream(serialize());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }
}