Pobieranie torrenta 16 GB za pomocą tabletu z 4 GB wolnego miejsca
Zadanie:
Jest komputer bez Internetu, ale istnieje możliwość przesłania pliku przez USB. Istnieje tablet z internetem, z którego można przenieść ten plik. Możesz pobrać wymagany torrent na swój tablet, ale nie ma wystarczającej ilości wolnego miejsca. Plik w torrentie jest jeden i duży.
Droga do rozwiązania:
Uruchomiłem torrent do pobrania. Kiedy wolne miejsce prawie się skończyło, wstrzymałem pobieranie. Podłączyłem tablet do komputera i przeniosłem plik z tabletu na komputer. Zatrzymałem się i ku mojemu zdziwieniu plik został utworzony ponownie, a torrent kontynuował pobieranie, jakby nic się nie stało.
Ze względu na to, że klient torrentowy ustawia flagę sparse na plik, w którym zapisuje otrzymane dane, system nie podejmuje próby zarezerwowania 16 GB od razu i nie wystąpi błąd przy próbie zapisu do pliku powyżej 4 GB.
Po czterokrotnym powtórzeniu procedury otrzymałem na komputerze cztery pliki zawierające różne części tego samego torrenta. Teraz pozostało tylko je połączyć. Procedura jest zasadniczo prosta. Należy zastąpić bajty zerowe inną wartością, jeśli istnieje ona na danej pozycji w jednym z czterech plików.
Wydawało mi się, że taki prosty program powinien znaleźć się w Internecie. Czy nikt nigdy nie spotkał się z takim problemem? Ale zdałem sobie sprawę, że nawet nie wiem, jakie słowa kluczowe go szukać. Dlatego na szybko stworzyłem skrypt Lua do tego zadania i teraz go zoptymalizowałem. Właśnie tym chcę się podzielić.
Pobieranie torrenta w częściach
rozpocznij pobieranie torrenta na pierwszym urządzeniu
poczekaj, aż ROM się zapełni
wstrzymaj pobieranie
prześlij plik na drugie urządzenie i dodaj cyfrę do nazwy pliku
wracamy do pierwszego punktu, aż plik zostanie pobrany całkowicie
Łączenie części w jeden plik
Po otrzymaniu ostatniej części należy zebrać je w jeden cały plik.
Zadanie jest proste:
Czytanie wszystkich części na raz
Jeśli w jakiejś części pozycja nie jest bajtem zerowym, to zapisujemy ją na wyjście, w przeciwnym razie zapisujemy zero
Funkcja merge_part akceptuje tablicę wątków streams_in z czego odczytuje część rozmiaru buffer_length i zwraca wynik łączenia części z różnych wątków.
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
--[[
Funkcja string.gsub nadaje się do tego zadania, ponieważ znajdzie kawałki wypełnione zerami i dostarczy to, co mu zostanie powierzone.
--]]
out_part = out_part:gsub(" +", function(zero_string)
if #in_part < find_index then
return -- не на что менять
end
--[[
string.gsub nie informuje o pozycji, w której znaleziono dopasowanie. Dlatego prowadzimy równoległe poszukiwanie stanowiska zero_string za pomocą funkcji string.find. Wystarczy znaleźć pierwszy bajt zerowy.
Teraz, jeśli w in_part są dane dla out_part skopiuj je.
--]]
if #in_part >= start_index then
local end_index = start_index + #zero_string - 1
--[[
Wytnij z in_part część odpowiadająca ciągu zer.
--]]
local part = in_part:sub(start_index, end_index)
if (part:byte(1) ~= 0) or part:find("[^ ]") then
--[[
В part są dane.
--]]
if #part == #zero_string then
return part
else
--[[
part okazała się mniejsza niż ciąg zer. Uzupełnijmy go nimi.
--]]
return part..zero_string:sub(1, end_index - #in_part)
end
end
end
end)
end
end
end
return out_part
end
wniosek
W ten sposób mogliśmy pobrać i złożyć ten plik na komputerze. Po fuzji wyciągnąłem plik torrent z tabletu. Zainstalowałem klienta torrent na moim komputerze i sprawdziłem za jego pomocą plik.
Ostatnią pobraną część na tablet można pozostawić w dystrybucji, ale przed tym należy włączyć ponowne sprawdzanie części i odznaczyć plik, aby nie pobierał się ponownie.