2014-09-19 91 views
-2

最近我一直在嘗試多線程,並編寫了一個應用程序,該應用程序使用HTTPUrlConnection的Range請求屬性下載文件。我首先從頭文件中獲得文件的長度,然後將它分成X個相等的部分,如果有剩餘部分,我再分配一個線程來彌補鬆弛。然後,每個部分進入隊列中的對象。然後多個線程訪問隊列中的每個任務並執行它,並將每個部分同時下載到單獨的文件中。多線程下載與單線程不同的文件

我加入文件的方式是問題。無論我使用的是Linux cat還是Windows的copy /Btype,它總是會出現結果文件以某種方式失效。

使用AVI文件時,索引被破壞,但重建時,AVI播放正確。 .rar文件winrar顯示「意外的歸檔結束」,儘管這些文件正常提取。什麼可能導致這一點。當我在線程之間分割時,我確信沒有字節重疊。

+0

你可以在你的問題上添加更多信息嗎?我認爲它很不清楚 – msrd0 2014-09-19 19:34:26

+1

我會下載(原始)完整文件,並在兩個平行窗口中執行原始文件和重新組裝的文件的十六進制轉儲。這樣你可以看到什麼內容是相同的,哪些內容是不同的。您提到的所有實用程序都是針對文本內容而非二進制文件的,所以如果您在這些二進制文件中使用這些文件時沒有正確行事,我不會感到驚訝。我將使用FileInputStream在所有下載完成後一次一個地重新讀取它們,並以正確的順序將它們寫入單個FileOutputStream中。 – Tim 2014-09-19 19:39:34

+0

我在十六進制編輯器中發現的是,對於我製作的每個零件,至少有一個字符偏移量。這些變化是波動的,我必須找出發生變化的地方。 – 2014-09-19 19:50:12

回答

0

您正在錯誤地將Range參數用於請求。結束索引是要讀取的最後一個字符,(含),而您的算法會傳遞您不想傳輸的第一個字符的索引。從你身上的end參數DownloadPart參數減去1,你應該罰款:

list.add(new DownloadPart(pos, pos + pieceLen - 1, savePath, url, String.valueOf(ch))); 

你還要代碼,你應該清理一些不必要的重複;您的第一個完整塊不需要與任何其他完整塊區別對待,這將簡化您的代碼。

+0

謝謝!我想我被困在剩菜的心態不同,所以我讓第一部分不必要地不同。 但它仍然是一個字節的短。這意味着FileSplitter:35會是: 'list.add(new DownloadPart(pos,byteSize,savePath,url,String.valueOf(ch)));' – 2014-09-19 20:41:52

+0

我會以不同的方式處理「剩菜」您應該只執行N次下載,而不是剩餘N + 1次,因爲執行HTTP連接只需幾個字節是無效的。因此,通過四捨五入來計算「pieceLen」,然後讓最後一塊比其他塊短一些。 – Tim 2014-09-19 20:48:40

+0

您也可以在循環中爲該循環迭代獲取多少個字節的變量;每次除了最後一次,還有'byteSize%pieces'都會成爲pieceLen。然後你可以在調用中使用它來構建一個DownloadPart並使用它,所以你不會複製那個代碼。 (而且更容易看出不同迭代之間有什麼不同。)總的來說,你想找到避免重寫代碼幾乎相同的方法;找出兩者之間的不同之處,將其拉入方法或變量或類中,然後使用它編寫複雜的代碼。 – Tim 2014-09-19 20:52:16