当前位置: 首页 > 面试题库 >

Java中可迭代的gzip压缩/膨胀

张宝
2023-03-14
问题内容

是否存在用于隐藏在Internet上的ByteBuffer的gzip压缩库?是什么让我们可以推送原始数据然后提取缩小的数据?我们已经搜索了它,但是仅找到处理InputStreams和OutputStreams的库。

我们的任务是创建gzip过滤器,以缩小管道体系结构中的ByteBuffers流。这是拉式体系结构,其中最后一个元素从较早的元素中提取数据。我们的gzip过滤器处理ByteBuffers流,没有单个Stream对象可用。

我们曾尝试将数据流调整为某种InputStream,然后使用GZipOutputStream满足我们的要求,但是至少可以说,适配器代码的数量很烦人。

接受后编辑 :为了便于记录,我们的体系结构类似于GStreamer等。


问题答案:

马克·阿德勒(Mark Adler)提出了这种方法,这一点值得称赞,这比我最初的回答要好得多。

package stack;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.zip.CRC32;
import html" target="_blank">java.util.zip.Deflater;

public class BufferDeflate2 {
    /** The standard 10 byte GZIP header */
    private static final byte[] GZIP_HEADER = new byte[] { 0x1f, (byte) 0x8b,
            Deflater.DEFLATED, 0, 0, 0, 0, 0, 0, 0 };

    /** CRC-32 of uncompressed data. */
    private final CRC32 crc = new CRC32();

    /** Deflater to deflate data */
    private final Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION,
            true);

    /** Output buffer building area */
    private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    /** Internal transfer space */
    private final byte[] transfer = new byte[1000];

    /** The flush mode to use at the end of each buffer */
    private final int flushMode;


    /**
     * New buffer deflater
     * 
     * @param syncFlush
     *            if true, all data in buffer can be immediately decompressed
     *            from output buffer
     */
    public BufferDeflate2(boolean syncFlush) {
        flushMode = syncFlush ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH;
        buffer.write(GZIP_HEADER, 0, GZIP_HEADER.length);
    }


    /**
     * Deflate the buffer
     * 
     * @param in
     *            the buffer to deflate
     * @return deflated representation of the buffer
     */
    public ByteBuffer deflate(ByteBuffer in) {
        // convert buffer to bytes
        byte[] inBytes;
        int off = in.position();
        int len = in.remaining();
        if( in.hasArray() ) {
            inBytes = in.array();
        } else {
            off = 0;
            inBytes = new byte[len];
            in.get(inBytes);
        }

        // update CRC and deflater
        crc.update(inBytes, off, len);
        deflater.setInput(inBytes, off, len);

        while( !deflater.needsInput() ) {
            int r = deflater.deflate(transfer, 0, transfer.length, flushMode);
            buffer.write(transfer, 0, r);
        }

        byte[] outBytes = buffer.toByteArray();
        buffer.reset();
        return ByteBuffer.wrap(outBytes);
    }


    /**
     * Write the final buffer. This writes any remaining compressed data and the GZIP trailer.
     * @return the final buffer
     */
    public ByteBuffer doFinal() {
        // finish deflating
        deflater.finish();

        // write all remaining data
        int r;
        do {
            r = deflater.deflate(transfer, 0, transfer.length,
                    Deflater.FULL_FLUSH);
            buffer.write(transfer, 0, r);
        } while( r == transfer.length );

        // write GZIP trailer
        writeInt((int) crc.getValue());
        writeInt((int) deflater.getBytesRead());

        // reset deflater
        deflater.reset();

        // final output
        byte[] outBytes = buffer.toByteArray();
        buffer.reset();
        return ByteBuffer.wrap(outBytes);
    }


    /**
     * Write a 32 bit value in little-endian order
     * 
     * @param v
     *            the value to write
     */
    private void writeInt(int v) {
        System.out.println("v="+v);
        buffer.write(v & 0xff);
        buffer.write((v >> 8) & 0xff);
        buffer.write((v >> 16) & 0xff);
        buffer.write((v >> 24) & 0xff);
    }


    /**
     * For testing. Pass in the name of a file to GZIP compress
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        File inFile = new File(args[0]);
        File outFile = new File(args[0]+".test.gz");
        FileChannel inChan = (new FileInputStream(inFile)).getChannel();
        FileChannel outChan = (new FileOutputStream(outFile)).getChannel();

        BufferDeflate2 def = new BufferDeflate2(false);

        ByteBuffer buf = ByteBuffer.allocate(500);
        while( true ) {
            buf.clear();
            int r = inChan.read(buf);
            if( r==-1 ) break;
            buf.flip();
            ByteBuffer compBuf = def.deflate(buf);
            outChan.write(compBuf);
        }

        ByteBuffer compBuf = def.doFinal();
        outChan.write(compBuf);

        inChan.close();
        outChan.close();
    }
}


 类似资料:
  • 使用的字符串: string='hello'+'\r\n'+'world' Java中的预期输出: out.getValue() f.write(Base64.b64Encode(Out.getValue())) F.Close() ByteArrayInputStream(压缩)); InputStreamReader(gis,“UTF-8”));

  • 问题内容: 我正在使用php的功能来执行HTTP请求。为了节省带宽,我决定使用添加标题。 显然,输出一个gzip编码的字符串,所以我用来解码该编码的字符串,但是将作为参数传递的数据出错。 我知道还有另一个功能可以解压缩压缩后的数据,但是它不包含在我的PHP版本中(也许仅在SVN上可用)。 我知道cUrl可以即时解码gzip流(没有任何问题),但是有人建议我使用它而不是cUrl。 您是否知道以其他方

  • 问题内容: 我想使用Gzip压缩来压缩java中的输入流。 假设我们有一个未压缩的输入流(1GB数据..)。因此,我需要从源压缩的输入流: 问题答案: DeflaterInputStream不是您想要的,因为它缺少gzip标头/预告片,并且使用略有不同的压缩方式。 如果从OutputStream(推)更改为InputStream(拉),则需要做不同的事情。 GzipOutputStream的作用是

  • 我想在JavaScript中做解压缩图像。我已经用C#使用gzip压缩了图像。如何在JavaScript中解压缩gzipped数据? C#代码

  • Gzip 中间件 Gzip 中间件使用 gzip 压缩方案来对HTTP响应进行压缩。 使用 e.Use(middleware.Gzip()) 自定义配置 使用 e := echo.New() e.Use(middleware.GzipWithConfig(middleware.GzipConfig{ Level: 5, })) 配置 GzipConfig struct { // Skipp