java wrap GZIPOutputStream и ByteArrayOutputStream вместе - что я делаю не так? - PullRequest
2 голосов
/ 04 августа 2011

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).

1 Ответ

6 голосов
/ 04 августа 2011

GZIPOutputStream выполняет некоторую внутреннюю буферизацию перед передачей данных следующему поток в цепочке (в данном случае ByteArrayOutputStream). Таким образом, вы должны закрыть () поток, прежде чем сможете прочитать байты обратно. Например, я сделал следующую модификацию для 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 () сам не делает этого, хотя, я пытался).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...