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();
}
}