【发布时间】:2019-03-27 09:06:54
【问题描述】:
我正在尝试在 Kotlin 中下载大文件 (this question 的答案。除了我使用的是 Kotlin 而不是 java,所以语法略有不同。
val client = OkHttpClient()
val request = Request.Builder().url(urlString).build()
val response = client.newCall(request).execute()
val is = response.body().byteStream()
val input = BufferedInputStream(is)
val output = FileOutputStream(file)
val data = ByteArray(1024)
val total = 0L
val count : Int
do {
count = input.read(data)
total += count
output.write(data, 0, count)
} while (count != -1)
output.flush()
output.close()
input.close()
它可以在不使用太多内存的情况下下载文件,但它似乎不必要地无效,因为它不断尝试写入更多数据而不知道是否有任何新数据到达。
在资源非常有限的虚拟机上运行它时,我自己的测试似乎也证实了这一点,因为它似乎使用更多的 CPU,但下载速度低于 python 中的类似脚本,并且使用wget。
我想知道是否有一种方法可以让我在 x 字节可用或文件结尾时调用回调,这样我就不必不断尝试获取更多数据知道有没有。
编辑: 如果使用 okhttp 无法实现,我使用其他东西没有问题,只是它是我习惯的 http 库。
【问题讨论】:
-
它确实知道更多的数据已经到达,因为
count等于接收到的数据量,并且它一直循环直到count是-1。还是我误会了什么? -
在调用
input.read(data)之前它并不知道,并且该函数可以返回 0 或其他非常小的数字。如果我准备好例如 1024 字节,我只想将新数据写入磁盘。 -
while ((count = input.read(data)) == 0) { Thread.sleep(50L); }(虽然没用过。) -
好吧,这至少会减少不必要的 CPU 周期,但也不能完全按照我的意愿去做,这会导致我的代码不会向磁盘写入“任何内容”,但它仍然会写入少量数据(如果 200 字节)到达磁盘。谢谢,如果没有其他建议,我会考虑它:)