在内存Zip异常错误中缩小和扩充Java字符串

时间:2016-03-30 15:01:41

标签: java zip deflate inflate

我正在编写代码来缩小和扩充base 64编码中的字符串,但是我收到以下错误:

n <- 10
set.seed(100)
d <- rep(NA, n)
d[1] <- 0
y <- runif(n)
a <- 220
mt = matrix(nrow = n, ncol = n)
mt[is.na(mt)] = 0
for (i in (2:(length(y)+1))) {
    d[i] <- d[i-1] + y[i-1]
}

store.x <- NULL
for(j in 1:a) {
    x <- runif(1, min = 0, max = sum(y))
    for (i in 1:(length(y))) {
        if(x <= d[i+1] && x > d[i]) {
            store.x[j] <- i

            if(length(which(i == store.x)) > 1){
                mt[which(mt[,i] != 0),i] = mt[which(mt[,i] != 0),i] + 1
            } else {
                mt[(which(rowSums(mt) == 0)[1]),i] = 1
            }

            break
        }
    }
}

我的代码是:

if(length(which(i == store.x)) > 1){
                    mt[which(mt[,i] != 0),i] = mt[which(mt[,i] != 0),i] + 1
                } else {
                    mt[(which(rowSums(mt) == 0)[1]),i] = 1
                }

我做错了什么?

2 个答案:

答案 0 :(得分:0)

这解决了我的所有问题,并且都是JDK用法:

package serializer.test;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.zip.*;

import javax.xml.bind.DatatypeConverter;

public class DeflationApp
{
    private String compressBase64(String stringToCompress, int level)
            throws UnsupportedEncodingException
    {
        byte[] compressedData = new byte[1024];
        byte[] stringAsBytes = stringToCompress.getBytes("UTF-8");

        Deflater compressor = new Deflater(level, false);
        compressor.setInput(stringAsBytes);
        compressor.finish();
        int compressedDataLength = compressor.deflate(compressedData);

        byte[] bytes = Arrays.copyOf(compressedData, compressedDataLength);
        return DatatypeConverter.printBase64Binary(bytes);
    }

    private String decompressToStringBase64(String base64String)
            throws UnsupportedEncodingException, DataFormatException
    {
        byte[] compressedData = DatatypeConverter
                .parseBase64Binary(base64String);

        Inflater deCompressor = new Inflater();
        deCompressor.setInput(compressedData, 0, compressedData.length);
        byte[] output = new byte[100000];
        int decompressedDataLength = deCompressor.inflate(output);
        deCompressor.end();

        return new String(output, 0, decompressedDataLength, "UTF-8");
    }

    public static void main(String[] args) throws DataFormatException,
            IOException
    {
        DeflationApp m = new DeflationApp();
        String strToBeCompressed = readFile(
                "C:\\codebase\\OverallSystem\\MappingMapToEBECommon.xslt")
                .trim();
        for (int i = 1; i <= 9; ++i)
        {
            String compressedData = m.compressBase64(strToBeCompressed, i);
            String deCompressedString = m.decompressToStringBase64(compressedData);

            System.out.println("Base 64:");
            System.out.println("Original Length with level("+i+"): " + strToBeCompressed.length());
            System.out.println("Compressed with level("+i+"): " + compressedData.toString());
            System.out.println("Compressed with level("+i+") Length: " + compressedData.toString().length());
            System.out.println("Decompressed with level("+i+"): " +
                    + deCompressedString.length());
            System.out.println("Decompressed with level("+i+"): " + deCompressedString);
        }

        for (int i = 1; i <= 9; ++i)
        {
            byte[] compressedData  = m.compress(strToBeCompressed, i);
            String deCompressedString = m.decompressToString(compressedData);

            System.out.println("Without Base 64:");
            System.out.println("Original Length with level("+i+"): " + strToBeCompressed.length());
            System.out.println("Compressed with level("+i+"): " + new String(compressedData));
            System.out.println("Compressed with level("+i+") Length: " + new String(compressedData).length());
            System.out.println("Decompressed with level("+i+"): " +
                    + deCompressedString.length());
            System.out.println("Decompressed with level("+i+"): " + deCompressedString);
        }

    }

    private byte[] compress(String stringToCompress, int level) throws UnsupportedEncodingException
    {
        byte[] compressedData = new byte[1024];
        byte[] stringAsBytes = stringToCompress.getBytes("UTF-8");

        Deflater compressor = new Deflater(level, false);
        compressor.setInput(stringAsBytes);
        compressor.finish();
        int compressedDataLength = compressor.deflate(compressedData);

        return Arrays.copyOf(compressedData, compressedDataLength);
    }

    private String decompressToString(byte[] compressedData) throws UnsupportedEncodingException, DataFormatException
    {   
        Inflater deCompressor = new Inflater();
        deCompressor.setInput(compressedData, 0, compressedData.length);
        byte[] output = new byte[100000];
        int decompressedDataLength = deCompressor.inflate(output);
        deCompressor.end();

        return new String(output, 0, decompressedDataLength, "UTF-8");
    }

    public static String readFile(String file) throws IOException
    {
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line = null;
        StringBuilder stringBuilder = new StringBuilder();
        String ls = System.getProperty("line.separator");

        try
        {
            while ((line = reader.readLine()) != null)
            {
                stringBuilder.append(line);
                stringBuilder.append(ls);
            }

            return stringBuilder.toString();
        }
        finally
        {
            reader.close();
        }
    }

}

答案 1 :(得分:0)

我也有使用DeflaterOutputStream的内存问题 - 如果让它使用默认构造函数,它会起作用。这很好用:

for (Entry<String, String> entry : valueMap.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue();                       
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DeflaterOutputStream dos = new DeflaterOutputStream(baos);
    try { 
        dos.write(value.getBytes());
        dos.flush();
        dos.close();
    }
    catch (IOException e) {
        throw new RuntimeException(e);
    }
    byte[] zipData = baos.toByteArray();
    zipValueMap.put(key, zipData);
}

但改为:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
Deflater deflater = new Deflater(Deflater.BEST_SPEED); 
DeflaterOutputStream dos = new DeflaterOutputStream(baos, deflater);

这给了我JVM C代码中的内存泄漏,占用了80g并且崩溃了我的薄荷系统。那么为什么默认构造函数会起作用呢?但是当我在其中传递自己的平减器失败时却非常糟糕:

解码DeflaterOutputStream(java 1.8_40)我在close方法中找到了一些特殊代码:

public void close() throws IOException {
    if (!closed) {
        finish();
        if (usesDefaultDeflater)
            def.end();
        out.close();
        closed = true;
    }
}

我猜他们把它放到了deflater的解决方法中。

最好的解决方案是在循环中明确地调用它:

try { 
    dos.write(value.getBytes());
    dos.flush();
    dos.close();
    deflater.end();
}

没有更多的内存泄漏。它也是一个糟糕的内存泄漏,因为它来自C端,因此它从不抛出JVM错误,它只是嚼掉了我所有的40g ram,然后开始交换空间。我不得不把它扔进盒子里然后杀了它。