问题:
有一台没有互联网的 PC,但可以通过 USB 传输文件。 有一台带有互联网的平板电脑,可以从中传输该文件。 您可以在平板电脑上下载所需的 torrent,但可用空间不足。 torrent 中的文件很大。
解决方案路径:
我开始下载种子。 当可用空间快用完时,我暂停了下载。 我将平板电脑连接到电脑,并将文件从平板电脑移动到电脑。 我停了下来,令我惊讶的是,文件又被创建了,并且 torrent 继续下载,就好像什么也没发生一样。
由于 torrent 客户端会在写入接收到的数据的文件中设置稀疏标志,因此系统不会尝试立即保留 16GB,并且在尝试写入超过 4GB 的文件时也不会发生错误。
重复该过程四次后,我在电脑上收到了四个文件,其中包含同一 torrent 的不同部分。 现在剩下的就是将它们放在一起。 该过程本质上很简单。 如果零字节存在于四个文件之一的给定位置,则需要将其替换为另一个值。
在我看来,这么简单的程序应该在互联网上。 难道没有人遇到过这样的问题吗? 但我发现我什至不知道用什么关键词来搜索它。 因此,我很快为这个任务创建了一个Lua脚本,现在我已经对其进行了优化。 这就是我想分享的。
分部分下载 torrent
- 开始在第一台设备上下载 torrent
- 等待ROM填满
- 暂停下载
- 将文件传输到第二台设备并在文件名中添加数字
- 我们返回第一点,直到文件完全下载
将各部分合并到一个文件中
收到最后一部分后,有必要将它们收集成一个完整的文件。
任务很简单:
- 一次性阅读所有部分
- 如果在某些部分该位置不是零字节,那么我们将其写入输出,否则我们写入零
功能 merge_part
接受线程数组 streams_in
其中读取 size 的一部分 buffer_length
并返回合并来自不同线程的部分的结果。
function merge_part(streams_in, buffer_length)
local out_part
for _, stream in ipairs(streams_in) do
local in_part = stream:read(buffer_length)
if not out_part then
out_part = in_part -- просто копируем часть из первого файла
elseif in_part and #in_part > 0 then
if #out_part < #in_part then
out_part, in_part = in_part, out_part
end
if out_part ~= in_part -- данные различаются
and in_part:find("[^ ]") -- есть данные в in_part
and out_part:find(" ", 1, true) -- есть пустые места в out_part
then
local find_index = 1
--[[
功能 string.gsub
适合该任务,因为它会找到充满零的碎片并交付给它的东西。
--]]
out_part = out_part:gsub(" +", function(zero_string)
if #in_part < find_index then
return -- не на что менять
end
--[[
string.gsub
不传达找到匹配项的位置。 因此,我们对位置进行并行搜索 zero_string
使用功能 string.find
。 找到第一个零字节就足够了。
--]]
local start_index = out_part:find(" ", find_index, true)
find_index = start_index + #zero_string
--[[
现在如果在 in_part
有数据为 out_part
复制它们。
--]]
if #in_part >= start_index then
local end_index = start_index + #zero_string - 1
--[[
剪自 in_part
对应于零序列的部分。
--]]
local part = in_part:sub(start_index, end_index)
if (part:byte(1) ~= 0) or part:find("[^ ]") then
--[[
В part
有数据。
--]]
if #part == #zero_string then
return part
else
--[[
part
结果小于零序列。 让我们用它们来补充它。
--]]
return part..zero_string:sub(1, end_index - #in_part)
end
end
end
end)
end
end
end
return out_part
end
结论
因此,我们能够在 PC 上下载并组装该文件。 合并后,我从平板电脑中取出种子文件。 我在我的电脑上安装了一个 torrent 客户端并用它检查了文件。
平板电脑上最后下载的部分可以保留在发行版中,但您需要在此之前启用对部分的重新检查,并取消选中该文件,以便它不会再次下载。
用过的:
- 平板电脑上的 Flud 种子客户端。
- PC 上的 Torrent 客户端 qBittorent。
Lua脚本
来源: habr.com