2014-09-19 93 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