有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java有没有一种方法可以检测传入的序列化对象流是GZIPOutputStream压缩的还是简单的ObjectOutputStream?

我有一个传统的系统,服务器会在几周内缓慢更新。层次结构如下:

1
2
3 4 5

1 is the client pc
2 is a master server
3 4 and 5 are servers across the country.

目前,所有这些都以未压缩格式来回发送POJO(普通旧java对象)。想想OjBectOutStream()等等

我希望压缩通过线路序列化的数据,但压缩方式应确保仅压缩从查询接收的数据。发送下来的数据是微不足道的(查询筛选数据)

只会立即更新客户端1和主服务器2。服务器#3、#4和#5可以每隔几周或几个月进行更新。我需要一种方法,使服务器2能够检测从3、#4或#5返回的流是否被压缩并相应地处理(当它们升级时)

-编辑- 对于服务器3、4和5,解决方案必须不引人注目。这些服务器没有在发生异常时重新发送数据的概念

下面是#2用于与#3、#4或#5通信的代码示例:

    // Set the content type to be application/x-java-serialized-object
    connection.setRequestProperty("Content-Type", "application/x-java-serialized-object");

    setupHeaderAttributes(getHttpHeaders());

    setupSessionCookies(getHttpHeaders());

    // Load/add httpHeaders
    addHeadersToConnection(connection, getHttpHeaders());

    // Write the serialized object as post data
    objectoutputstream = new ObjectOutputStream(connection.getOutputStream());
    objectoutputstream.writeObject(obj);
    objectoutputstream.flush();

    // Get ready to receive the reply.
    inputstream = connection.getInputStream();
    setHttpStatus(connection.getResponseCode());

这可能吗?谢谢你抽出时间

-丹尼斯


共 (3) 个答案

  1. # 1 楼答案

    您可以读取流的标题GZIPOutputStream先将GZIP头写入流中,然后再执行其他操作,在词汇十六进制中,它看起来像:

    0x1f8b 0800 0000 0000 0000
    

    Source

    请注意,如果您的旧服务器没有使用Java的GZIPOutputStream,那么最后8个字节可能会有所不同。然而,the first 2 bytes will always be ^{}。剩下的头值只是关于它来自哪里的信息,以及GZIP格式使用的一些其他标志

  2. # 2 楼答案

    @Puce有一半的答案。另一半是使用mark()reset()重置流(如果它不是gzip流):

        InputStream in = // stream from server
        in = new BufferedInputStream(in);
        in.mark(1024);
    
        try {
            in = new GZIPInputStream(in);
        }
        catch (ZipException ex) {
            in.reset();
        }
    
        // "in" is now ready for use
    

    这里的BufferedInputStream有两个用途:首先,我知道它支持标记/重置。第二,如果底层流没有被缓冲,它将提高IO性能(尽管,如果它是套接字流,它将被缓冲)

    1024的标记值是任意值。GZipInputStream构造函数应该能够通过读取前两个字符来确定底层流是否被gzip压缩。然而,GZIP头是10字节长的,所以它可能会尝试读取更多。它不应该读取超过1024字节(如果读取超过1024字节,则增加标记值)


    编辑:因为我从您的编辑中看到您正在使用内容类型头,所以您也可以使用它来选择性地解压缩流:新服务器将返回类似x-application/java-gzipped-serialized-object的内容,而旧服务器继续返回x-application/serialized-java-object(或其他内容)

    以“x-”开头的内容类型不受限制;只要双方同意,你想用什么就用什么

  3. # 3 楼答案

    如果constructors of GZIPInputStream无法处理输入流,则会抛出ZipException

    ZipException - if a GZIP format error has occurred or the compression method used is unsupported