任務:
有一台沒有網路的 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腳本
來源: www.habr.com