簡體   English   中英

有沒有辦法檢測傳入的序列化對象流是壓縮的GZIPOutputStream還是簡單的ObjectOutputStream?

[英]Is there a way to detect if an incoming serialized object stream is GZIPOutputStream compressed or a simple 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對象)。 想想OjbectOutputStream()等。

我想壓縮通過網絡序列化的數據,但這樣做的方式是只壓縮從查詢接收的數據。 發送的數據是微不足道的(查詢過濾器數據)。

只有客戶端#1和主服務器#2立即更新。 服務器#3,#4和#5可以相隔數周或數月更新。 我需要一種方法讓服務器#2能夠檢測從#3,#4或#5返回的流是否被壓縮並相應地處理它(當它們升級時)。

-EDIT-對於服務器#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());

這可能嗎? 感謝您的時間。

丹尼斯

您可以在流的標題中讀取。 GZIPOutputStream在其他任何內容之前將GZIP標頭寫入流中,在詞法十六進制中,它看起來像:

0x1f8b 0800 0000 0000 0000

資源

請注意,如果舊版服務器未使用Java的GZIPOutputStream ,則最后8個字節可能不同。 但是, 前2個字節將始終為0x1f8b 其余的標頭值只是關於它來自何處以及GZIP格式使用的其他標志的信息。

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

    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個字節(如果是,則增加標記值)。


編輯:因為我從您的編輯中看到您正在使用Content-Type標頭,您還可以使用它來選擇性地解壓縮流:新服務器將返回類似x-application/java-gzipped-serialized-object而舊服務器繼續返回x-application/serialized-java-object (或其他任何東西)。

以“x-”開頭的內容類型不受限制; 只要兩端都同意,你就可以使用你想要的任何東西。

如果GZIPInputStream構造函數無法處理輸入流,則拋出ZipException。

ZipException - 如果發生GZIP格式錯誤或不支持使用的壓縮方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM