Mam problem z napisaniem kodu na wypakowywanie plików (coś koło 400MB) w środowisku C++ Builder 10. Wcześniej próbowałem z ZipForge, ale okazało się że trzeba zapłacić 50 euro żeby tego używać, a ja piszę żeby się uczyć. Jakie są inne sposoby na wypakowywanie? Wiem że było już takie pytanie, ale nie jest już aktualne.
Ogólnie to najprościej by było użyć np. darmowego 7zip'a który występuje w wersji samodzielnej (7za.exe) nie potrzebującej instalacji uruchamianej z wiersza poleceń. Możesz uruchomić go z niezbędnymi parametrami, jak plik do rozpakowania oraz ścieżka docelowa ukrywając okno CMD i zadziała Ci to ładnie. Możesz nawet wtedy przechwycić wyjście i wyświetlić w memo.
Już tak próbowałem. A jest inny sposób? Zależy mi na progressbar
W sumie teraz sobie przypomniałem, że VCL od jakiegoś czasu ma tą klasę http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.Zip.TZipFile ze zdarzeniem http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.Zip.TZipFile.OnProgress które można oprogramować aby pokazać postęp.
Mam wersję 10.2, nie mam tego. Chyba musi być przez aplikację zewnętrzną, trudno. Tylko co w takim razie zrobić żeby nie było hourglass'a zamiast ikony i żeby nie szarzał ekran?
Wyświetl statyczny formularz z informacją:
Trwa wypakowywanie plików – idź na kawę, ja se to sam zrobię...
i odpal kod z wątku pobocznego.
Nie jest to złe rozwiązanie – nawet Windows często nie pokazuje postępu, po prostu wyświetla tekst aby czekać i tyle. Wątek poboczny uchroni Cię przed zamrożeniem programu – aplikacja będzie przetwarzać komunikaty, więc m.in. okno będzie w razie potrzeby odmalowywane.
A jak to zrobić? Nie znam się na tworzeniu procesów.
Ale co zrobić? Nie wiesz jak wyświetlić formularz, czy jak stworzyć wątek poboczny?
Do wątków jest artykuł na stronie producenta – How To Build Multithreaded Applications – poczytaj.
Napisałem to wcześniej w komentarzu, ale zgodnie z sugestią, że lepiej takie coś wrzucić jako post - wklejam tutaj treść tego komentarza :D
Animowane kółeczko to jest jakaś opcja. Wprawdzie ściema, ale bardzo skutecznie uspokajająca klienta :D
A co do braku stosownej biblioteki - wiem, czytałem całość wątku. Chodziło mi o to, że może jednak ktoś coś sensowego zaproponuje. http://www.asawicki.info/news_1368_lzma_sdk_-_how_to_use.html - tam jest fragment "g_ProgressCallback is a pointer to a C "interface" (let's call it this way ;P) where you can place your callback with progress notification"
Wygląda na to że wątki są dla mnie za trudne. Nie da się tego jakoś inaczej zrobić?
wojciennie napisał(a):
Wygląda na to że wątki są dla mnie za trudne.
Wielowątkowość ogólnie jest rzeczą trudną i wymagającą dłuższej nauki, jednak istnienie klasy TThread
ułatwia imeplementację.
Nie da się tego jakoś inaczej zrobić?
W tym przypadku raczej nie – albo wykonujesz kod w ramach głównego wątku, tym samym całkowicie zamrażając działanie aplikacji na czas ekstrakcji plików z archiwum, albo umieszczasz kod obsługi archiwum w wątku pobocznym, pozwalając na swobodny przepływ komunikatów.
Gdybyś miał wiele krótkotrwałych operacji do wykonania, to mógłbyś po każdej z nich odpalać metodę ProcessMessages
, w celu obsługi komunikatów zalegających w kolejce. Dla użytkownika nie było by to widoczne, o ile faktycznie te operacje były by krótkotrwałe. Jednak ty masz jedną, dużą i długotrwałą operację, więc tego nie da się tutaj zastosować.
Dałoby się, gdybyś mógł podłączyć swoje zdarzenie, które było by wykonywane często, np. po skończeniu zapisu na dysku każdego pojedynczego pliku z archiwum. Wtedy w takim zdarzeniu mógłbyś wywołać metodę ProcessMessages
, regularnie odmrażając interfejs. I wcale nie było by to takie złe rozwiązanie – pod warunkiem, że dobrze zaimplementowane. Funkcjonalność co prawda była by nieco inna, jednak coś za coś.
wojciennie napisał(a):
Mam wersję 10.2, nie mam tego. Chyba musi być przez aplikację zewnętrzną, trudno. Tylko co w takim razie zrobić żeby nie było hourglass'a zamiast ikony i żeby nie szarzał ekran?
Ale jak to nie mam? Ta klasa jest od wersji XE2, więc musisz ją mieć. Nawet w wersji Starter. Tak przynajmniej wynika z tego dokumentu https://www.embarcadero.com/docs/Delphi-Feature-Matrix.pdf na stronie 8.
Ja bym polecał bibliotekę libarchive. I nie trzeba się wcale babrać z wątkami, tylko po prostu wypakowywać i zapisywać do pliku po kawałku, po każdym kawałku uaktualniając pasek postępu i przyjmując ewentualne wejście od użytkownika.
Dopiero teraz zabrałem się za dalsze robienie tej aplikacji. Zdecydowałem, że spróbuję zrobić coś z tymi wątkami. Co jest nie tak?
Plik cpp z wątkami: https://pastebin.com/Sh2SCHsD
Plik nagłówkowy z watkami: https://pastebin.com/d7Cvug6u
Wywołanie:
TDecompress *myThread = new myThread(true);
myThread->Priority = tpHigher;
myThread->Start();
Błędy (wszystko wskazuje na pierwszą linijkę wywołania)
[bcc32 Error] Unit1.cpp(250): E2303 Type name expected
[bcc32 Error] Unit1.cpp(250): E2034 Cannot convert 'int *' to 'TDecompress *'
[bcc32 Error] Unit1.cpp(250): E2141 Declaration syntax error
TDecompress *myThread = new myThread(true);
TDecompress *myThread = new TDecompress(true);
Z każdą bzdurą będziesz na forum uderzał?