Качаем 16GB торэнт праз планшэт з 4GB вольнага месца
задача:
Ёсць ПК без інтэрнэту, але ёсць магчымасць перакінуць файл па USB. Ёсць планшэт з інтэрнэтам з якога гэты файл можна перакінуць. На планшэт можна спампаваць патрэбны торэнт але мала вольнага месца. Файл у торэнце адзін і вялікі.
Шлях да рашэння:
Я запусціў торэнт на загрузку. Калі свабоднае месца амаль падышло да канца я паставіў загрузку на паўзу. Падлучыў планшэт да ПК і перамясціў файл з планшэта на ПК. Адціснуў паўзу і да майго здзіўлення файл быў зноў створаны і торэнт працягнуў пампавацца далей як ні ў чым не бывала.
Дзякуючы таму што торэнт кліент усталёўвае sparse сцяг файла ў які запісвае атрыманыя дадзеныя сістэма не спрабуе зарэзерваваць адразу 16GB і не паўстане памылкі пры спробе запісу ў файл далей 4GB.
Паўтарыўшы працэдуру чатыры разы я атрымаў на ПК чатыры файлы у якім розныя часткі аднаго і таго ж торэнта. Цяпер засталося сабраць іх разам. Працэдура па сутнасці простая. Трэба замяніць нуль байты на іншае значэнне, калі яно ёсць у дадзенай пазіцыі ў адным з чатырох файлаў.
Мне падавалася што такая простая праграмка павінна быць у інтэрнэце. Няўжо ніхто не сутыкаўся з такой задачай? Але я зразумеў, што нават не ведаю па якіх ключавых словах яе шукаць. Таму я хутка накідаў Lua скрыпт пад гэтую задачу а зараз ужо і аптымізаваў яго. Ім і хачу падзяліцца.
Загружаем торэнт па частках
запускаем загрузку торэнта на першай прыладзе
чакаем пакуль запоўніцца ПЗУ
ставім загрузку на паўзу
пераносім файл на другую прыладу і дадаем да імя файла лічбу.
вяртаемся да першага пункта датуль пакуль файл не запампуецца цалкам
Зліваем часткі ў адзін файл
Пасля таго як атрымана апошняя частка неабходна сабраць іх у адзін цэлы файл.
Задача простая:
Чытаем усе часткі адначасова
Калі ў нейкай частцы ў пазіцыі не нулявы байт то пішам на вынахад яго інакш пішам нуль
Функцыя merge_part прымае масіў патокаў streams_in з якіх чытае частку памерам 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. Досыць знайсці першы нулявы байт.
Цяпер калі ў 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
Заключэнне
Такім чынам атрымалася спампаваць і сабраць гэты файл на ПК. Пасля зліцця я выцягнуў з планшэта торэнт файл. Усталяваў на ПК торэнт кліент і праверыў ім файл.
Апошнюю запампаваную частку на планшэце можна пакінуць на раздачы але трэба ўключыць перад гэтым паўторную праверку частак і зняць галачку з файла каб ён зноўку не спампоўваўся.