OutOfMemoryError同时将zip文件分为两部分

时间:2014-12-08 08:13:18

标签: glassfish-3 fileinputstream fileoutputstream java-6

我的应用程序将.zip文件分成两部分。当文件大小小于100MB时,它工作正常。如果文件大小超过100MB,则给出

java.lang.OutOfMemoryError
    at java.io.FileInputStream.readBytes(Native Method)
    at java.io.FileInputStream.read(FileInputStream.java:198)

我使用glassfishV3和JDK6

-Xms512m -Xmx512m还不够

then I have set 
<jvm-options>-Xms1024m</jvm-options>
<jvm-options>-Xmx1024m</jvm-options>

然后它给出了

"Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine."

public void create() {
    byte[] bFile = takeByteArr("file1.zip");
    byte[] bPart1 = Arrays.copyOfRange(bFile, 0, 100000);
    byte[] bPart2 = Arrays.copyOfRange(bFile, 100000, bFile.length);
    createFile(bPart1, "part1.zip");
    createFile(bPart2, "part2.zip");
}

void createFile(byte[] bFile, String path) {
    try {
        FileOutputStream fos = new FileOutputStream(path);
        fos.write(bFile);
        fos.close();
    } catch (FileNotFoundException ex) {
        System.out.println("FileNotFoundException : " + ex);
    } catch (IOException ioe) {
        System.out.println("IOException : " + ioe);
    }
}

byte[] takeByteArr(String filePath) {
    File file = new File(filePath);
    byte[] bFile = new byte[(int) file.length()];
    try {
        FileInputStream  fileInputStream = new FileInputStream(file);
        fileInputStream.read(bFile);
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bFile;
}

1 个答案:

答案 0 :(得分:0)

正如评论中已经建议的那样,大文件不是在一个部分中读取,而是在较小的缓冲区中读取。然后处理缓冲区,在这种情况下,这将把部分文件保存到磁盘,并在循环中重用,该循环按块读取文件块。这种方法的优点是你只需要与缓冲区大小一样多的内存。

FileInputStream类有一个名为read(byte[] b, int off, int len)的方法,它在字节数组 b 中读取从 off 开始的 len 字节数来自InputStream。该方法返回一个int,表示在方法调用期间读取的字节数,如果没有任何内容可以读取,则返回 -1

示例:

    byte[] b = new byte[1024];
    int read = inputStream.read(b, 0, 1024);

现在你有一个字节数组 b ,它是1024字节大,包含字节的内容。

您可以循环浏览文件,但必须注意最后一部分。字节数组缓冲区也将具有100000的大小,但我想你不想创建具有该大小的最后一部分。因此,您必须重新创建具有字节数的缓冲区,这实际上是内容的最后部分。

您的代码可能如下所示:

public void create() throws IOException {
    FileInputStream in = new FileInputStream(new File("file1.zip"));

    byte[] b = new byte[100000];
    int read;
    int counter = 0;
    while ((read = in.read(b, 0, 100000)) != -1) {
        if(read != 100000) { // <- the last part
            b = Arrays.copyOfRange(b, 0, read);
        }
        createFile(b, "part" + counter++ + ".zip");
        b = new byte[100000];
    }  
}