0

このテスト:

import java.util.zip.Deflater;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.filter.support.Zlib;
import org.junit.*;

public class ZlibTest {
    private Deflater deflater = null;

    private Zlib inflater = null;

    @Before
    public void setUp() throws Exception {
        deflater = new Deflater(Deflater.BEST_COMPRESSION);
        deflater.setStrategy(Deflater.DEFAULT_STRATEGY);
        inflater = new Zlib(Zlib.COMPRESSION_MAX, Zlib.MODE_INFLATER);
    }

    @Test
    public void testInflate() throws Exception {
        byte[] compressed = new byte[14];
        deflater.setInput(new byte[] {1});
        deflater.finish();
        int bytesCompressed = deflater.deflate(compressed);
        IoBuffer compressedBuffer = IoBuffer.wrap(compressed, 0, bytesCompressed);
        System.out.println(compressedBuffer);

        IoBuffer byteUncompressed = inflater.inflate(compressedBuffer);
    }
}

失敗します:

java.io.IOException: Unknown error. Error code : 1
    at org.apache.mina.filter.support.Zlib.inflate(Zlib.java:136)
    at ZlibTest.testInflate(ZlibTest.java:29)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
    at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

ここで何が問題になっていますか?

更新:追加した場合

        case JZlib.Z_STREAM_END:

Zlib.javaの139行目までは、正常にデコードされます。

4

3 に答える 3

2

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4255743 (有名な 13 年前のバグ - 私の子供だったらすぐに高校に行くだろう) に関しては、修正が Java で提供されています。7 (ついに); 確かに、ある

public int deflate(byte[] b, int off, int len, int flush) {
    if (b == null) {
        throw new NullPointerException();
    }
    if (off < 0 || len < 0 || off > b.length - len) {
        throw new ArrayIndexOutOfBoundsException();
    }
    synchronized (zsRef) {
        ensureOpen();
        if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
            flush == FULL_FLUSH)
            return deflateBytes(zsRef.address(), b, off, len, flush);
        throw new IllegalArgumentException();
    }
}

コードのセクションが Deflater クラスに追加されました。そのため、今日 (2012 年)、必要な機能がすべて java.util である場合は、java.util に固執することができます。

于 2012-06-05T17:14:34.317 に答える
2

JZlib の作成の原因となった Java Deflater クラスの「設計上の選択」に達しました。zlib のFLUSHパラメーターを制御することはできません。

{1} の 1 バイト配列に対する Deflater クラスからの出力:

[0] 120 
[1] -38 
[2] 99  
[3] 4   
[4] 0   
[5] 0   <<
[6] 2   <<
[7] 0   <<
[8] 2   <<

{1} の 1 バイト配列を収縮するときの Zlib クラスからの出力:

[0] 120 
[1] -38 
[2] 98  
[3] 4   
[4] 0   
[5] 0   <<
[6] 0   <<
[7] -1  <<
[8] -1  <<

Zlibマニュアルより

パラメータ flush が Z_SYNC_FLUSH に設定されている場合、保留中のすべての出力が出力バッファにフラッシュされ、出力がバイト境界に整列されるため、デコンプレッサはこれまでに利用可能なすべての入力データを取得できます。(特に、呼び出しの前に十分な出力スペースが提供されている場合、呼び出しの後の avail_in はゼロです。) フラッシングは一部の圧縮アルゴリズムの圧縮を低下させる可能性があるため、必要な場合にのみ使用する必要があります。これにより、現在の deflate ブロックが完成し、3 ビットと次のバイトまでのフィラー ビットで構成される空の格納ブロックが続き、その後に 4 バイト (00 00 ff ff) が続きます

JZlib から - なぜ JZlib なのか?

Java Platform API は、zlib にアクセスするためのパッケージ「java.util.zip.*」を提供しますが、zlib のエッセンスを使用する必要がある場合、そのサポートは非​​常に制限されます。たとえば、純粋な Java SSH システムにパケット圧縮サポートを追加するには、zlib へのフル アクセスが必要でしたが、これらは要件には役に立ちません。...

この機能を実装するには、zlib の Z_PARTIAL_FLUSH モードを使用する必要がありますが、JDK では許可されていません。この問題はよく知られているようで、すでに JavaSoft の BugParade に報告されている方もいらっしゃるようですが (BugId:4255743 など)、JavaSoft から肯定的な回答が返ってきていないため、この問題が永遠に解決されることはありません。これが、JZlib をハッキングする動機です。

于 2011-04-04T10:17:14.863 に答える
-1

Zlib と Inflater/deflater がデータの送信に同じデータ プロトコルを使用しているとは思いません。それらは同じ基本的な圧縮を使用している可能性がありますが、Zlib はストリームに生データだけでなく、独自に使用される情報が含まれていることを期待していると思われます。


Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
deflater.setStrategy(Deflater.DEFAULT_STRATEGY);

byte[] compressed = new byte[10];
deflater.setInput(new byte[]{1});
deflater.finish();
int bytesCompressed = deflater.deflate(compressed);
System.out.println("bytesCompressed=" + bytesCompressed + " " + Arrays.toString(compressed));

Inflater inflater = new Inflater();
inflater.setInput(compressed, 0, bytesCompressed);
byte[] decompressed = new byte[2];
int byteDecompressed = inflater.inflate(decompressed);

System.out.println("bytesInflated=" + byteDecompressed + " " + Arrays.toString(decompressed));

版画

bytesCompressed=9 [120, -38, 99, 4, 0, 0, 2, 0, 2, 0]
bytesInflated=1 [1, 0]
于 2011-04-04T08:13:20.847 に答える