Качаємо 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

Додати коментар або відгук