java - GZIP Streams 的序列化/反序列化不一致

标签 java serialization gzip throwable

我有以下代码尝试序列化/反序列化 Throwable

public void test() throws IOException, ClassNotFoundException {
    IllegalStateException exception = new IllegalStateException("Oooops!");

    ByteBuffer seralized = serialize(exception);
    String asString = new String(seralized.array(), Charset.forName("UTF-8"));

    Throwable deserialized = deserialize(seralized);

    // false
    System.out.println(exception.equals(deserialized));
    // true
    System.out.println(exception.toString().equals(deserialized.toString()));

    seralized = serialize(deserialized);
    String toCompare = new String(seralized.array(), Charset.forName("UTF-8"));
    // true
    System.out.println(asString.equals(toCompare));
}

private Throwable deserialize(ByteBuffer seralized) throws IOException, ClassNotFoundException {
    return (Throwable) new ObjectInputStream(new GZIPInputStream(
            new ByteArrayInputStream(seralized.array()))).readObject();
}

private ByteBuffer serialize(Throwable exception) throws IOException {
    ByteArrayOutputStream causeBytesOut = new ByteArrayOutputStream();
    ObjectOutputStream causeOut = new ObjectOutputStream(
                                         new GZIPOutputStream(causeBytesOut));
    causeOut.writeObject(exception);
    causeOut.close();
    return ByteBuffer.wrap(causeBytesOut.toByteArray());
}

解释代码:我正在测试我的序列化/反序列化是否兼容。

第一个打印输出(错误)告诉我,反序列化后得到的内容与序列化后得到的内容不同。

第二个打印(true)表明这些对象“有些”相似。

我试图深入研究每个对象,看看有什么区别,所以我再次序列化它并查看字节缓冲区的内容。根据最后一次打印,这看起来是相同的(正确)。

为什么初始对象和经过序列化/反序列化的对象虽然看起来相同,但不同?

最佳答案

请对您观察到的结果进行以下解释。

  1. 调用 toStringIllegalStateException 类型的对象上将简单地返回完全限定的类名。这是来自Throwable#toString() 。因此这对于两个对象来说是相同的,equals 的结果将会是真的

    java.lang.IllegalStateException
    
  2. IllegalStateException或者它的 parent 不会覆盖 equals方法。因此将仅等于其自身。由于您的反序列化将创建一个新对象,因此您的对象在引用中不相等,因此 equals将返回 false(根据 Object#equals )。

  3. 您正在创建 asStringtoCompare完全相同的方式,使用下面的表达式,也因为这两个具有相同内容的不同字符串对象将相等,所以你的第三个表达式是正确的。

    new String(seralized.array(), Charset.forName("UTF-8"));
    

如果您需要让反序列化对象在调用 equals() 时返回 true使用原始对象,您可以子类 IllegalStateException并覆盖equals方法(在本例中也是 toString。)。

关于java - GZIP Streams 的序列化/反序列化不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41986506/

相关文章:

Java SimpleDateFormat 在 Date 对象中返回错误值

java - 无法加载 ApplicationContext : IllegalArgumentException

python - 使用 Python 解压缩数据包的 gzip 有效负载

php - 用 PHP 解压缩 Tiled TMX 文件内容

asp.net-mvc - 合并、最小化和 gzip ASP.NET MVC 的 CSS 和 JavaScript 文件

java - Spring Stomp over Websocket : Message/Buffer/Cache/Stream limits

java - 如何在谷歌登录另一个 Activity 后保存谷歌个人资料

java - Jersey 的 jackson ,一个实体有多个序列化程序

c++ - 使用私有(private)数据 boost 类的序列化

c# - 仅反序列化 XML 中的特定项目并添加到列表