簡體   English   中英

使用 RandomAccessFile 類寫入大文件

[英]Write big files using RandomAccessFile class

我需要將大文件 (GB) 復制到另一個文件(容器)中,我想知道性能和內存使用情況。

像下面這樣讀取整個源文件:

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

            }
        }

嘗試使用 async nio Channel


    public void copyFile(String src, String target) {
        final String fileName = getFileName(src);
        try (FileChannel from = (FileChannel.open(Paths.get(src), StandardOpenOption.READ));
                FileChannel to = (FileChannel.open(Paths.get(target + "/" + fileName), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE))) {
            transfer(from, to, 0l, from.size());
        }
    }

    private String getFileName(final String src) {
        File file = new File(src);
        if (file.isFile()) {
            return file.getName();
        } else {
            throw new RuntimeException("src is not a valid file");
        }
    }

    private void transfer(final FileChannel from, final FileChannel to, long position, long size) throws IOException {
        while (position < size) {
            position += from.transferTo(position, Constants.TRANSFER_MAX_SIZE, to);
        }
    }

這將創建一個讀寫異步通道,並有效地將數據從第一個傳輸到后一個。

使用FileInputStreamFileOutputStream讀取塊/塊,例如一次 64k。

如果您需要提高性能,您可以嘗試使用線程,一個線程用於讀取,另一個線程用於寫入。

您還可以使用直接 NIO 緩沖區來提高性能。
參見例如關於何時應該將直接緩沖區與 Java NIO 一起用於網絡 I/O 的簡單規則?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM