Качаем 16GB торэнт праз планшэт з 4GB вольнага месца

Качаем 16GB торэнт праз планшэт з 4GB вольнага месца

задача:

Ёсць ПК без інтэрнэту, але ёсць магчымасць перакінуць файл па USB. Ёсць планшэт з інтэрнэтам з якога гэты файл можна перакінуць. На планшэт можна спампаваць патрэбны торэнт але мала вольнага месца. Файл у торэнце адзін і вялікі.

Шлях да рашэння:

Я запусціў торэнт на загрузку. Калі свабоднае месца амаль падышло да канца я паставіў загрузку на паўзу. Падлучыў планшэт да ПК і перамясціў файл з планшэта на ПК. Адціснуў паўзу і да майго здзіўлення файл быў зноў створаны і торэнт працягнуў пампавацца далей як ні ў чым не бывала.

Дзякуючы таму што торэнт кліент усталёўвае sparse сцяг файла ў які запісвае атрыманыя дадзеныя сістэма не спрабуе зарэзерваваць адразу 16GB і не паўстане памылкі пры спробе запісу ў файл далей 4GB.

Паўтарыўшы працэдуру чатыры разы я атрымаў на ПК чатыры файлы у якім розныя часткі аднаго і таго ж торэнта. Цяпер засталося сабраць іх разам. Працэдура па сутнасці простая. Трэба замяніць нуль байты на іншае значэнне, калі яно ёсць у дадзенай пазіцыі ў адным з чатырох файлаў.

Мне падавалася што такая простая праграмка павінна быць у інтэрнэце. Няўжо ніхто не сутыкаўся з такой задачай? Але я зразумеў, што нават не ведаю па якіх ключавых словах яе шукаць. Таму я хутка накідаў Lua скрыпт пад гэтую задачу а зараз ужо і аптымізаваў яго. Ім і хачу падзяліцца.

Загружаем торэнт па частках

  1. запускаем загрузку торэнта на першай прыладзе
  2. чакаем пакуль запоўніцца ПЗУ
  3. ставім загрузку на паўзу
  4. пераносім файл на другую прыладу і дадаем да імя файла лічбу.
  5. вяртаемся да першага пункта датуль пакуль файл не запампуецца цалкам

Зліваем часткі ў адзін файл

Пасля таго як атрымана апошняя частка неабходна сабраць іх у адзін цэлы файл.

Задача простая:

  1. Чытаем усе часткі адначасова
  2. Калі ў нейкай частцы ў пазіцыі не нулявы байт то пішам на вынахад яго інакш пішам нуль

Функцыя 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. Досыць знайсці першы нулявы байт.

--]]
                    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

Заключэнне

Такім чынам атрымалася спампаваць і сабраць гэты файл на ПК. Пасля зліцця я выцягнуў з планшэта торэнт файл. Усталяваў на ПК торэнт кліент і праверыў ім файл.

Апошнюю запампаваную частку на планшэце можна пакінуць на раздачы але трэба ўключыць перад гэтым паўторную праверку частак і зняць галачку з файла каб ён зноўку не спампоўваўся.

Выкарыстоўваліся:

  1. Торэнт кліент Flud на планшэце.
  2. Торэнт кліент qBittorent на ПК.
  3. Lua скрыпт

Крыніца: habr.com

Дадаць каментар