3

Main.java

import java.io.IOException;

public class Main
{

    private final CompressedOutputStream    m_cos;

    public static void main(String[] args)
    {
        try
        {
            final Main m = new Main(new CompressedOutputStream());
            m.run();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public Main(final CompressedOutputStream cos)
    {
        this.m_cos = cos;
    }

    private void trace(final String format, Object... args)
    {
        final String output = String.format(format, args);
        System.out.println(output);
    }

    public void run()
    {
        this.first_write();
        this.second_write();
        this.trace("CRC32 of data is %x", this.m_cos.get_crc32());
    }

    private void add_data(final byte[] data)
    {
        try
        {
            this.m_cos.write(data); // STEPPING INTO THIS IN DEBUG DOESN'T LEAD ANYWHERE!
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public void first_write()
    {
        final String[] text_lines = new String[] { "Hello world!",
                "My name is Joe.", "Nice to meet.", "Where are you from?",
                "I'm from Congo" };

        for (final String text_line : text_lines)
        {
            final byte[] data = text_line.getBytes();
            this.add_data(data);
        }

        final byte[] compressed_data = this.m_cos.get_compressed_data();
        trace("Compressed data length (so far) is %d bytes",
                compressed_data.length);
    }

    public void second_write()
    {
        final byte[] additional_data = new byte[] { 0x00, 0x01, 0x02, 0x03,
                0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
        this.add_data(additional_data);

        final byte[] total_compressed_data = this.m_cos.get_compressed_data();
        trace("Total compressed data length is %d bytes",
                total_compressed_data.length);
    }
}

CompressedOutputStream.java

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.Deflater;
import java.util.zip.GZIPOutputStream;

public class CompressedOutputStream extends GZIPOutputStream
{

    private final ByteArrayOutputStream m_out;

    public CompressedOutputStream() throws IOException
    {
        this(32);
    }

    public CompressedOutputStream(int size) throws IOException
    {
        super(new ByteArrayOutputStream(size), size);
        this.m_out = (ByteArrayOutputStream) this.out;
        this.def.setLevel(Deflater.BEST_COMPRESSION);
    }

    public long get_crc32()
    {
        return this.crc.getValue();
    }

    public byte[] get_compressed_data()
    {
        return this.m_out.toByteArray();
    }
}

したがって、GZIPOutputStream と ByteArrayOutputStream を結合しようとするこのコードがあります。

何らかの理由で、私が得ているのは同じ10バイトだけです。
この出力の取得:

圧縮されたデータの長さ (これまで) は 10 バイトです
圧縮されたデータの合計の長さは 10 バイト
です データの CRC32 は 4550d94d です

write() を呼び出すと、最終的に抽象関数になるようです。つまり、どこにも到達せず、何も書き込まれません。
オンザフライで書き込み、圧縮し、後で圧縮されたバイトを取得できるようにしたい。

ここで何が欠けていますか?些細なことのようですが、そうではありません。

編集#1:私の最終目標
明確にするために:最後に必要なのは、シーケンスではなくチャンクで書き込むメモリ内バッファだけであり、Xバイトに達した時点でこれらの圧縮およびチェックサムされたバイトを取得できます(標準のJavaストリームではなく、どこかに書き込むため)。

4

1 に答える 1

6

GZIPOutputStream は、チェーン内の次のストリーム (この場合は ByteArrayOutputStream) にデータを渡す前に、内部バッファリングを行います。したがって、バイトを読み戻す前に、ストリームを close() する必要があります。たとえば、second_write() に次の変更を加えました。

this.m_cos.close();
final byte[] total_compressed_data = this.m_cos.get_compressed_data();
trace("Total compressed data length is %d bytes", total_compressed_data.length);

これにより、次の出力が得られました。

圧縮されたデータの長さ (これまで) は 10 バイトです
圧縮されたデータの合計の長さは 98 バイト
です データの CRC32 は 4550d94d です

ストリームを閉じる余裕がない場合は、閉じずに内部バッファーを強制的にフラッシュする方法があるかもしれません。(flush() 自体はそうしませんが、私は試しました)。

于 2011-08-04T16:10:38.607 に答える