Java使用Byteoutputstream编写大型文件

Java使用Byteoutputstream编写大型文件,java,Java,我正试图使用ByteArrayOutputStream编写一个大小在1kb到10GB之间的文件,但引发了下面的异常。我正在使用JDK6。请推荐更好的高性能Api。我使用相同的网络盒进行读写 Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit at java.util.Arrays.copyOf(Unknown Source) a

我正试图使用
ByteArrayOutputStream
编写一个大小在1kb到10GB之间的文件,但引发了下面的异常。我正在使用JDK6。请推荐更好的高性能Api。我使用相同的网络盒进行读写

Exception in thread "main" java.lang.OutOfMemoryError:   Requested array size exceeds VM limit
        at java.util.Arrays.copyOf(Unknown Source)
        at java.io.ByteArrayOutputStream.grow(Unknown Source)
        at java.io.ByteArrayOutputStream.ensureCapacity(Unknown Source)
        at java.io.ByteArrayOutputStream.write(Unknown Source)
        at java.io.OutputStream.write(Unknown Source)
        at
代码:

import java.io.BufferedOutputStream;
导入java.io.ByteArrayOutputStream;
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.FileOutputStream;
公共类预文件{
/**
*@param args
*@抛出异常
*/
公共静态void main(字符串[]args)引发异常{
//TODO自动生成的方法存根
新建PrepareFile().constructFile(“f:\\hello”,“f:\\output”,10000000);
}
//通过复制,使用小尺寸的输入文件数据写入10 GB的大文件
公共void构造函数文件(字符串文件名、字符串输出路径、整数乘数)引发异常{
BufferedOutputStream fos=null;
FileInputStream fis=null;
最终文件输入文件=新文件(文件名);
字符串路径=inputFile.getParent();
if(outPath!=null&&!outPath.isEmpty()){
路径=输出路径;
}
fis=新文件输入流(文件名);
试一试{
//读取输入文件中的事务。
字节[]txnda=新字节[(int)inputFile.length()];
fis.read(txnData);
最终文件输出文件=新文件(路径,“Myfile”);
fos=新缓冲输出流(新文件输出流(输出文件));
最终ByteArrayOutputStream bas=新ByteArrayOutputStream();
final ByteArrayOutputStream=1=新ByteArrayOutputStream();
//乘数如果输入文件大小为1KB,输出文件大小为10GB,则乘数值为(1024*1024)
对于(长i=1;i=40000&&i%40000==0){
System.out.println(“现在的i值:+i”);
资产负债表(fos);
重置();
//写(txnData);
}
//写事务
写(txnData);
baos1.write(txnda);//此行出现异常
}
int Padding=myCustomMethod(baos1.toByteArray());
//将所有输出数据写入输出流
资产负债表(fos);
paos.flush();
1.flush();
}捕获(例外e){
e、 printStackTrace();
}最后{
fos.close();
fis.close();
}
}
公共int myCustomMethod(字节[]b){
//需要完整的字节来准备文件拖车
返回0;
}
}

由于大小是32位有符号的,
ByteArrayOutputStream中不能有2 GB或更多的缓冲区

如果您想提高性能,我会逐步处理文件,并避免如此大的内存拷贝,因为它们非常昂贵

顺便说一句,我有一个库,它支持大于2GB的缓冲区,可以使用本机内存并映射到文件,以避免使用堆,并且可以大于主内存

但是,如果您逐步处理数据,则不需要如此大的缓冲区

我还建议您使用Java8,因为它比十年前发布的Java6执行64位操作更好


根据您的代码进行编辑,无需使用ByteArrayOutputStream,您可以逐步准备文件

//Writes a large file of 10 GB using input file data of small size by duplicating
public void constructFile(String fileName, String outFileName, int multiplier) throws IOException {
    byte[] bytes;
    try (FileInputStream fis = new FileInputStream(fileName)) {
        bytes = new byte[fis.available()];
        fis.read(bytes);
    }

    try (FileOutputStream fos = new FileOutputStream(outFileName)) {
        for (int i = 0; i < multiplier; i++) {
            fos.write(bytes);
        }
    }

    // now process the file "outFileName"
    // how depends on what you are trying to do.
    // NOTE: It is entirely possible the file should be processed as it is written.
}
//通过复制,使用小尺寸的输入文件数据写入10GB的大文件
公共void构造函数文件(字符串文件名、字符串outFileName、int乘数)引发IOException{
字节[]字节;
try(FileInputStream fis=newfileinputstream(文件名)){
字节=新字节[fis.available()];
fis.读取(字节);
}
try(FileOutputStream fos=newfileoutputstream(outFileName)){
对于(int i=0;i
尽管非常极端,但您可以制作一个超级ByteArrayOutputStream,其中隐藏了多个ByteArrayOutputStreams(以下示例使用其中3个,最大容量为6 GB):

公共类LargeByteArrayoutOutputStream扩展了OutputStream{
私有DirectByteArrayOutputStream b1=新的DirectByteArrayOutputStream(Integer.MAX_值-8);
私有DirectByteArrayOutputStream b2=新的DirectByteArrayOutputStream(Integer.MAX_值-8);
私有DirectByteArrayOutputStream b3=新的DirectByteArrayOutputStream(Integer.MAX_值-8);
私有长posWrite=0;
私有长posRead=0;
@凌驾
公共无效写入(int b)引发IOException{
if(posWriteposWrite){
返回(int)-1;
}否则{
字节b=0;
if(posRead//Writes a large file of 10 GB using input file data of small size by duplicating
public void constructFile(String fileName, String outFileName, int multiplier) throws IOException {
    byte[] bytes;
    try (FileInputStream fis = new FileInputStream(fileName)) {
        bytes = new byte[fis.available()];
        fis.read(bytes);
    }

    try (FileOutputStream fos = new FileOutputStream(outFileName)) {
        for (int i = 0; i < multiplier; i++) {
            fos.write(bytes);
        }
    }

    // now process the file "outFileName"
    // how depends on what you are trying to do.
    // NOTE: It is entirely possible the file should be processed as it is written.
}
public class LargeByteArrayOutputOutputStream extends OutputStream {

    private DirectByteArrayOutputStream b1 = new DirectByteArrayOutputStream(Integer.MAX_VALUE -8);
    private DirectByteArrayOutputStream b2 = new DirectByteArrayOutputStream(Integer.MAX_VALUE -8);
    private DirectByteArrayOutputStream b3 = new DirectByteArrayOutputStream(Integer.MAX_VALUE -8);

    private long posWrite = 0;
    private long posRead = 0;
    @Override
    public void write(int b) throws IOException {
        if (posWrite < b1.getArray().length) {
            b1.write(b);
        } else if (posWrite < ((long)b1.getArray().length + (long)b2.getArray().length)) {
            b2.write(b);
        } else {
            b3.write(b);
        }
        
        posWrite++;

    }
    
    public long length() {
        return posWrite;
    }

    /** Propably you may want to read afterward */      
    public int read() throws IOException 
    {
        if (posRead > posWrite) {
            return (int)-1;
        } else {
            byte b = 0;
            if (posRead < b1.getArray().length) {
                b = b1.getArray()[(int)posRead];
            } else if (posRead < ((long)b1.getArray().length + (long)b2.getArray().length)) {
                b = b2.getArray()[(int)(posRead - b1.getArray().length)];
            } else {
                b = b3.getArray()[(int)(posRead - ((long)b1.getArray().length + (long)b2.getArray().length))];
            }
            
            posRead++;
            return b;
        }
    }       
}


public class DirectByteArrayOutputStream extends java.io.ByteArrayOutputStream {

 public DirectByteArrayOutputStream(int size) {
   super(size);
 }

 /**
 * Reference to the byte array that backs this buffer.
 */
 public byte[] getArray() {
   return buf;
 }       

 protected void finalize() throws Throwable
 {
  super.finalize();
 }
}