簡體   English   中英

寫下載文件的部分區域

[英]Writing partial region of downloaded file

我正在分別從互聯網上下載文件。 像3個地區。 假設我必須下載一個大小為1024kB的文件,我將該區域設置為0-340kB,341 - 680kB和681kB - 1024 kB。 我有每個部分的單獨的線程。 但是,我現在遇到的問題是,將下載的文件內容寫入單個文件。

由於我們有3個線程,每個線程都會下載需要按順序寫入文件的部分。

我怎樣才能做到這一點? 我想有3個臨時文件並寫入它們。 寫完所有文件后,我必須逐個文件讀取並寫入單個文件。 我覺得這有點開銷。 還有其他更好的方法嗎?

提前致謝。

要清楚,我不相信這種方法實際上會提高下載速度。 但是,如果從多個鏡像下載相同的文件,它可能會提供更一致的下載速度。

首先,如果您的文件不是太大,您可以在寫出之前緩沖所有文件。 因此,分配一個所有線程都可以訪問的緩沖區:

byte[] buf = new byte[fileSize];

現在您創建一個合適的Thread類型:

public class WriterThread extends Thread
{
    byte[] buf;
    int write_pos, write_remaining;

    public WriterThread(byte[] buf, int start, int len)
    {
        this.buf = buf;
        this.write_pos = start;
        this.write_remaining = len;
    }

    @Override
    public void run()
    {
        try (Socket s = yourMethodForSettingUpTheSocketConnection();
             InputStream istream = s.getInputStream()) {
            while (this.write_remaining > 0) {
                int read = istream.read(this.buf, this.write_pos, this.write_remaining);
                if (read == -1) error("Not enough data received");
                this.write_remaining -= read;
                this.write_pos += read;
            }
            // otherwise you are done reading your chunk!
        }
    }
}

現在,您可以使用合適的開頭和長度啟動這些WriterThread對象。 例如,對於大小為6000字節的文件:

byte[] buf = new byte[6000];
WriterThread t0 = new WriterThread(buf, 0, 3000);
WriterThread t1 = new WriterThread(buf, 3000, 3000);
t0.start();
t1.start();
t0.join();
t1.join();
// check for errors

請注意這里的重要位:每個WriterThread都有一個完全相同的緩沖區的引用,只是它開始寫入的不同偏移量。 當然,您必須確保yourMethodForSettingUpTheSocketConnection請求從偏移量this.write_pos開始請求數據; 如何做到這一點取決於您使用的網絡協議,超出您的要求。

如果您的文件太大而無法放入內存,則此方法無效。 相反,您將不得不使用(較慢)方法首先創建一個大文件,然后寫入該文件。 雖然我沒有嘗試過,但您應該能夠使用java.nio.file.File.newByteChannel()' to set up a suitable SeekableByteChannel as your output file. If you create such a as your output file. If you create such a SeekableByteChannel sbc`,那么您應該可以這樣做

sbc.location(fileSize - 1); // move to the specified position in the file
sbc.write(java.nio.ByteBuffer.allocate(1)); // grow the file to the expected final size

然后在每個線程中使用一個不同的SeekableByteChannel對象,指向磁盤上的同一文件,並使用SeekableByteChannel.location(int)方法設置寫入起始位置。 你需要一個臨時的byte[] ,你可以在其周圍包裝一個ByteBuffer (通過ByteBuffer.wrap() ),否則策略類似於上面的:

thread_local_sbc.location(this.write_pos);

然后每個thread_local_sbc.write()將寫入從this.write_pos開始的文件。

暫無
暫無

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

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