【问题标题】:File from multithreaded download different from single threaded来自多线程下载的文件不同于单线程
【发布时间】:2014-09-19 19:23:29
【问题描述】:

我最近一直在试验多线程,我编写了一个应用程序,该应用程序可以下载具有 HTTPUrlConnection 的 Range 请求属性的文件。我首先从标题中获取文件的长度,然后将其分成 X 个相等的部分,如果有剩余部分,我会再分配一个线程来填补空缺。然后每个部分进入队列内的一个对象。然后多个线程访问队列中的每个任务并执行它,同时将每个部分下载到单独的文件中。

我加入文件的方式是问题所在。无论我使用 Linux cat 还是 Windows 的 copy /Btype,总是会发现生成的文件以某种方式无效。

对于 AVI 文件,索引已损坏,但在重建时,AVI 可以正常播放。使用 .rar 文件时,winrar 会显示“存档意外结束”,尽管文件提取正常。这可能是什么原因造成的。当我在线程中拆分它时,我确保没有字节重叠。

【问题讨论】:

  • 您能否就您的问题添加更多信息?我认为它非常不清楚
  • 我会下载(原始)完整文件并在两个并行窗口中对原始文件和重新组装的文件进行十六进制转储。这样您就可以看到哪些内容相同,哪些内容不同。您提到的所有实用程序都适用于文本内容而不是二进制文件,因此当您将它们与这些二进制文件一起使用时,如果它们的行为不正确,我不会感到惊讶。我会改为使用FileInputStreams 在全部下载后一次重新读取您的片段,并以正确的顺序将它们写入单个FileOutputStream
  • 我在十六进制编辑器中发现的是,我制作的每个部分至少有一个字符偏移量。变化是涟漪,我必须找出变化发生的地方。
  • 你能发布你的代码吗?
  • 是的,我会把它贴在 Gist gist.github.com/anonymous/350b1a911cae5c3725ca "queue" 包中的库是我自己制作的,但这只是为了处理线程。

标签: java httpurlconnection


【解决方案1】:

您对请求的 Range 参数使用不正确。结束索引是要读取的最后一个字符,包含,而您的算法会传递您不想传输的第一个字符的索引。从作为end 参数传递给DownloadPart 的参数中减去1,你应该没问题:

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

您还有一些不必要的重复代码,您可能应该清理它们;您的第一个完整块不需要与任何其他完整块有任何不同的处理,这将简化您的代码。

【讨论】:

  • 谢谢!我想我被困在剩菜不同的心态中,所以我让第一部分不必要地不同。但它仍然短一个字节。这是否意味着 FileSplitter:35 将是:'list.add(new DownloadPart(pos, byteSize, savePath, url, String.valueOf(ch)));'
  • 我会以不同的方式处理“剩菜”;您应该只下载 N 次,而不是 N+1 次下载,因为只为几个字节进行 HTTP 连接是低效的。所以计算pieceLen,向上取整而不是向下取整,然后让最后一块比其他部分短一点。
  • 您还可以在循环中使用一个变量来确定该循环迭代需要多少字节;每次都是pieceLen,但最后一次,最后一次是byteSize % pieces。然后您可以在调用中使用它来构造一个 DownloadPart 并使用它,这样您就不会复制该代码。 (并且更容易看出不同迭代之间的不同之处。)一般来说,您希望找到避免重写几乎相同的代码的方法;找出两者之间的不同之处,将其提取到方法或变量或类中,然后使用它编写复杂的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多