【问题标题】:How provides to use small area while compressing and decompressing in java?java中如何在压缩和解压时使用小面积?
【发布时间】:2016-08-24 10:39:07
【问题描述】:

我有一个庞大的数据,当它进入 TextZip 类时,它在 RAM 中覆盖了大约 2 GB 的区域。我无法解决如何缩小该区域。我应该在那节课上改变什么?在java中压缩和解压缩时提供速度和小面积的任何替代方案或技术? 这是我的课程,名称为 TextZip.java ==>

https://gist.github.com/anonymous/bd72fee48e1c3f8812ece187080e452e

最好的问候。

【问题讨论】:

  • 巨大的数据到底是什么意思?这是否意味着您分别传递了很长的字符串作为compress()decompress() 方法的输入参数?
  • 3627829 字节被压缩。解压后变成 129531542 字节。它在 RAM 中覆盖 2 GB 的区域。有时它会抛出“OutOfMemory”错误。什么是 TextZip 类的替代品以覆盖 RAM 上的小区域?

标签: java zip buffer compression


【解决方案1】:

TextZipByteArrayOutputStream 中积累未压缩的数据并动态增长。但它始终将所有数据保存在 RAM 中。这就是您收到OutOfMemory 错误的原因。

考虑这样的事情(为简洁起见,我省略了异常捕获):

    ...
    OutputStream outputFile = new FileOutputStream("uncompressed"); // uncompressed data will be stored into file
    byte[] smallBuf = new byte[1024000];
    ByteArrayOutputStream largeBuf = new ByteArrayOutputStream();
    while (!decompressor.finished()) {
        int count = decompressor.inflate(smallBuf);
        largeBuf.write(smallBuf, 0, count);
        if (largeBuf.size() > 1024000 * 10) { // we already accumulated large chunk of data
            largeBuf.writeTo(outputFile);     // so it's time to write it to disk
            largeBuf.flush();
            largeBuf = new ByteArrayOutputStream(); // prepare for next large chunk
        }
    }
    ...

在上面的 sn-p 中,并非所有未压缩的数据都驻留在 RAM 中(显然,2GB 太多了)。但是将每一小块数据写入文件(或发送到网络)效率低下(因为 I/O 开销)。所以我们将未压缩的数据累积成大块(大约 10 兆字节),然后将这 10MB 写入磁盘。

一般来说,这是一个平衡的问题。将所有未压缩的数据驻留在 RAM 中速度很快,但受可用内存量的限制。由于 I/O,在 RAM 中保留小块未压缩数据会很慢。为您的机器调整循环内的条件。

【讨论】:

  • 在 java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) 在 java.lang .Thread.run(Thread.java:662) 引起:javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1] 消息:prolog 中不允许内容。在 com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:594) 在 com.thoughtworks.xstream.io.xml.StaxReader.pullNextEvent(StaxReader.java:58) ... 31更多它抛出这个错误。应该怎么做?
【解决方案2】:
        public static synchronized String decompress(String compressedData) throws IOException {
        // Create the decompressor and give it the data to compress
//        Inflater decompressor = new Inflater();
        byte[] buffer = new Base64Encoder().decode(compressedData);
//    System.out.println("Created string from bytes by base 64 encoding");
        OutputStream outputFile = new FileOutputStream("unCompressed");
        byte[] smallBuf =new byte[1024];
        decompressor.setInput(buffer);
        // Create an expandable byte array to hold the decompressed data
        ByteArrayOutputStream largeBuf = new ByteArrayOutputStream();

        // Decompress the data
        byte[] buf = new byte[10240];
        while (!decompressor.finished()) {

            try {
                int count = decompressor.inflate(buf);
                largeBuf.write(smallBuf, 0, count);
                if (largeBuf.size()>10240*10) {
                    largeBuf.writeTo(outputFile);
                    largeBuf.flush();
                    largeBuf=new ByteArrayOutputStream();
                }
            } catch (DataFormatException e) {
//                  System.out.println("Exception " + e);
            }

        }
        try {
            largeBuf.close();
        } catch (IOException e) {
        }

        // Get the decompressed data
        byte[] decompressedData = largeBuf.toByteArray();

        decompressor.reset();
//        decompressor.end();

        return new String(decompressedData);
    }

我重新设计了我的解压方法。是真的吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    相关资源
    最近更新 更多