2012-05-08 36 views
0

有什麼辦法從開放套接字流中隨機讀取字節?假設我在網站上打開了一個數據流。傳統的java類讓我能夠順序訪問數據。像一個鏈表。我想隨機讀取數據,例如從數組的隨機位置讀取數據。假設如果數據大小是2048 KB,我想從1到1204 KB讀取一個線程,同時要使用另一個線程讀取1205到2048 KB的數據。使用java從套接字流中讀取多個流?

所以底線是我想從一個網站的打開的套接字多線程的數據讀取過程。這個過程必須像Internet Download Manager一樣。 請給我一些教程鏈接,如果它可能..

+0

簡答:不,因爲流不是隨機訪問。 –

+0

如果你正在尋找自己的下載管理器,你應該閱讀HTTP範圍請求。流不按照你想要的方式工作。 –

+0

然後是否可以指定請求上的字節位置? 所以我將能夠使用2個或更多線程一次讀取同一個流的不同位置的數據。它會帶來更多的性能增益嗎? @PhilippReichart –

回答

3

使用多個線程從一個網站的流中隨機位置讀取是不可能的。數據以線性流的形式出現,並且沒有標準的方法可以在多個線程中訪問流中的不同位置。多線程可以但同時下載不同的文件。

HTTPD協議確實支持Range: header,雖然我不確定有多少web服務器支持這種行爲 - 例如Apache。

Accept-Ranges: bytes 

然後,客戶可以要求一個特定的偏差的文件/長度:

Range: bytes=21010-47021 

有了這個,你可以有多個線程如果得到支持,服務器應與下面的頭回應同時下載不同的範圍,但我不確定這將如何加速下載,除非您從多個服務器請求。您很可能會遇到磁盤和網絡限制。

1

來自套接字的數據按順序到達。你必須使用一些相當大的緩衝來避免這種情況。

0

您無法通過套接字隨機讀取。原則上,您有兩種選擇:

  1. 讀取整個數據流並將其放入一個緩衝區(例如字節數組)。向每個線程公開緩衝區。

  2. 獨立讀取每個線程中的整個數據流,讓每個線程忽略不應讀取的所有內容。

1

我thinkt你問的是HTTP報頭

Accept-Ranges: bytes 
Range: bytes=0-8999 

這將指示服務器只發送了一些文件。然後您將順序讀取流。

又見How to assemble the file using the range header?

編輯:例如

這似乎是工作

public static void main(String[] args) throws MalformedURLException, IOException { 
    URLConnection conn = new URL("http://ftp.debian.org/debian/dists/stable/Contents-i386.gz") 
      .openConnection(); 
    conn.addRequestProperty("Accept-Ranges","bytes"); 
    conn.addRequestProperty("Range", "bytes=8000000-16000000"); 
    InputStream input = conn.getInputStream(); 
    List<String> serverranges = conn.getHeaderFields().get("Accept-Ranges"); 
    boolean ispartial = serverranges != null && serverranges.get(0).equals("bytes"); 
    byte[] b = new byte[1024]; 
    int l ; 
    System.out.println(ispartial); 
    while((l=input.read(b, 0, b.length))>0){ 
     // if isPartial=true, we have server support. We received partial file. 
     //do stuff with b,l 
    } 
} 

要注意,並非所有的服務器都支持這一點很重要,所以檢查isPartial變量。如果它是假的。服務器不支持部分範圍,並會給你文件的開始。

+0

其實我是新來的java和沒有網絡的經驗。 所以,如果你可以給你一個剛纔用java說的例子,它會非常有用。 :) –

+0

我已經添加了一個例子 –