Java 使用RandomAccessFile类编写大文件

Java 使用RandomAccessFile类编写大文件,java,randomaccessfile,Java,Randomaccessfile,我需要将大文件(GBs)复制到另一个文件(容器)中,我想知道性能和ram使用情况 按如下方式读取整个源文件: RandomAccessFile f = new RandomAccessFile(origin, "r"); originalBytes = new byte[(int) f.length()]; f.readFully(originalBytes); 然后,将所有内容复制到容器中,如下所示: RandomAccessFile f2 = new RandomAccessFile(de

我需要将大文件(GBs)复制到另一个文件(容器)中,我想知道性能和ram使用情况

按如下方式读取整个源文件:

RandomAccessFile f = new RandomAccessFile(origin, "r");
originalBytes = new byte[(int) f.length()];
f.readFully(originalBytes);
然后,将所有内容复制到容器中,如下所示:

RandomAccessFile f2 = new RandomAccessFile(dest, "wr");
f2.seek(offset);
f2.write(originalBytes, 0, (int) originalBytes.length);
内存中的所有内容都正确吗?所以复制大文件会影响内存,并导致OutOfMemory异常

逐字节而不是完全读取原始文件是否更好? 那样的话,我该怎么办? 先谢谢你

编辑:

根据mehdi maick的回答,我终于找到了解决方案: 我可以使用RandomAccessFile作为目标,因为RandomAccessFile有一个方法“getChannel”返回一个FileChannel,所以我可以将该方法传递给以下方法,该方法将在我想要的目标位置复制文件(每次32KB):

     public static void copyFile(File sourceFile, FileChannel destination, int position) throws IOException {
            FileChannel source = null;
            try {
                source = new FileInputStream(sourceFile).getChannel();
                destination.position(position);
                int currentPosition=0;
                while (currentPosition < sourceFile.length())
                    currentPosition += source.transferTo(currentPosition, 32768, destination);
            } finally {
                if (source != null) {
                    source.close();
                }

            }
        }
publicstaticvoidcopyfile(文件源文件、文件通道目标、int位置)引发IOException{
filechannelsource=null;
试一试{
source=新文件输入流(sourceFile).getChannel();
目的地。位置(位置);
int currentPosition=0;
while(currentPosition
使用
FileInputStream
FileOutputStream
以块/块的形式读取,例如一次读取64k

如果需要提高性能,可以尝试使用线程,一个线程用于读取,另一个线程用于写入

您还可以使用直接NIO缓冲区提高性能。

请参阅例如,尝试使用异步nio
通道


公共无效复制文件(字符串src,字符串目标){
最终字符串文件名=getFileName(src);
try(filechannelfrom=(FileChannel.open(path.get(src),StandardOpenOption.READ));
FileChannel to=(FileChannel.open(path.get(target+“/”+fileName)、StandardOpenOption.CREATE\u NEW、StandardOpenOption.WRITE))){
传输(从,到,0升,从.size());
}
}
私有字符串getFileName(最终字符串src){
文件=新文件(src);
if(file.isFile()){
返回文件.getName();
}否则{
抛出新的运行时异常(“src不是有效文件”);
}
}
私有无效传输(最终文件通道从、最终文件通道到、长位置、长大小)引发IOException{
while(位置<大小){
位置+=从.transferTo(位置,常数.TRANSFER\u最大大小,到);
}
}

这将创建一个读写异步通道,并将数据高效地从第一个通道传输到第二个通道。

为什么不使用字节缓冲区,分块读取原始文件?性能非常好。分块读取,例如,一次读取64k,使用
FileInputStream
FileOutputStream
@AlexandarPetrov,考虑到目标文件必须使用RandomAccessFile编写,您能否提供一个示例?谢谢你。@Andreas,给你同样的东西;)为什么必须使用
RandomAccessFile
写入目标文件?您不是简单地将现有文件连接到一个组合文件中吗?如果最后一个64k块只包含32K字节,它会发生什么情况?它将写入整个64k(最后32k带零)?@navy1978如果只将32k读入缓冲区,它为什么会写入64k?如果是的话,你写错了代码。我不明白你的意思,你说要读64K字节,不是我。。。我在问你,如果最后一个数据块只包含32K(该文件实际上可能不是64K的倍数),它会发生什么?你觉得有意义吗?@navy1978你有一个缓冲区,例如64K大小,你要求将输入文件中的字节读到缓冲区,然后你反过来写实际读取到输出文件中的字节数。你到底为什么会认为写字节的代码不知道缓冲区是否满了?我在问,因为我不知道它是如何工作的,在RandomAccessFile中,方法“write”(其中一种方法“write”)获取一个字节数组,所以我想知道上次传递一个64kb的数组时,它会写入全部字节还是只写入部分字节。。。这是我的疑问…容器(目标文件)包含文件的串联,我需要在容器中寻找正确的偏移量并从那里开始写入。这就是为什么我在问题中问了一个例子,在这个例子中,我们使用RandomAccessFile写入目的地(容器)…您能否使用RandomAccessFile为目的地修改您的例子?
FileChannel
提供了一个
位置(长位置)
方法来查找所需的确切位置。我以前没有见过它。。我会投票给你,因为我现在无法测试,如果可以的话,我会接受你的答案。。。暂时谢谢你;)谢谢我接受了你的回答,我用我找到的答案编辑了我的问题…;)很高兴我能帮忙;)