Dekompresja danych [zlib]

dział ogólny

Dekompresja danych [zlib]

Nowy postprzez Gusław » środa, 30 czerwca 2010, 16:52

Witam!

Jestem nowy na forum,a swoją przygodę z programowaniem zacząłem niedawno. Proszę więc o wyrozumiałość. :)

A więc:
Napisałem 'program' który loguje się na stronkę, wszystko cacy (obsługa ciastek itd.). Chcę, aby serwer zwracał do mnie informacje w postaci skompresowanej (wiadomo, przyspieszy to ściąganie o te kilka ms). No i tu się zaczynają schody.
Doczytałem,że świetnie radzi sobie z tym biblioteka zlib, więc ją ściągnąłem,dodałem do projektu, cacy. :)

Ale.. nie wiem czemu, ale nie mogę sobie poradzić z dekompresją danych ze strumienia (MemoryStream). Nie wiem jak pobrać wielkość (nie bijcie!) takiej zmiennej. Z dekompresją/kompresją plików poradziłem sobie i kod wygląda tak:

Kompresja:
Kod: Zaznacz cały
fstream plikplik_po_zpakowaniu;
plik.open("zakoduj.txt",ios::in|ios::binary);
plik.seekg(0,ios::end);
unsigned int dlugosc_pliku plik.tellg();
plik.seekg(0,ios::beg);
unsigned charbufor = new unsigned char[dlugosc_pliku];
for(
unsigned int i 0;i<dlugosc_pliku;i++)
{
plik.read((char*)&bufor[i],1);
}
unsigned long dlugosc_po_zpakowaniu dlugosc_pliku 15;
unsigned charbufor_docelowy = new unsigned char[dlugosc_po_zpakowaniu];
compress2(bufor_docelowy,&dlugosc_po_zpakowaniu,bufor,dlugosc_pliku,Z_BEST_COMPRESSION);
plik_po_zpakowaniu.open("zakodowany.zlib",ios::binary|ios::out);
for(
unsigned int i 0i<dlugosc_po_zpakowaniu;i++)
{
plik_po_zpakowaniu.write((char*)&bufor_docelowy[i],1);
}
plik.close();
plik_po_zpakowaniu.close();
 


Dekompresja:
Kod: Zaznacz cały
fstream plikplik_po_rozpakowaniu;
plik.open("zakodowany.zlib",ios::binary|ios::in);
plik.seekg(0,ios::end);
int dlugosc_pliku plik.tellg();
plik.seekg(0,ios::beg);
charbufor = new char[dlugosc_pliku];
for(
int i 0;i<dlugosc_pliku;i++)
{
plik.read((char*)&bufor[i],1);
}
unsigned long dlugosc_po_rozpakowaniu=100000;
charbufor_docelowy = new char[dlugosc_po_rozpakowaniu];
uncompress(bufor_docelowy,&dlugosc_po_rozpakowaniu,bufor,dlugosc_pliku);
plik_po_rozpakowaniu.open("rozpakowany.txt",ios::binary|ios::out);
for(
unsigned int i 0i<dlugosc_po_rozpakowaniu;i++)
{
plik_po_rozpakowaniu.write((char*)&bufor_docelowy[i],1);
}
plik.close();
plik_po_rozpakowaniu.close(); 


Działa to elegancko, ale raczej przeszkadzałoby mi tworzenie w locie takich małych pliczków, dekompresję itd. Więc moje pytanie brzmi:
Jak pobrać wielkość MemoryStream i później ją zdekompresować.


Pozdrawiam i dziękuję za uwagę. :)

P.S.
Trochę zagmatwałem, ale mam nadzieję, że zrozumieliście.
Avatar użytkownika
Gusław
Bladawiec
Bladawiec
 
Posty: 2
Dołączył(a): środa, 30 czerwca 2010, 16:36
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP Home
Kompilator: C++ Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: Dekompresja danych [zlib]

Nowy postprzez Cyfrowy Baron » środa, 30 czerwca 2010, 18:17

Nie słyszałem o tym by archiwa zip obsługiwały dekompresję archiwów wczytanych do pamięci. Można co prawda pobrać dane z archiwum zip do strumienia, ale dane z pliku lokalnego, nie da się tego zrobić z plikiem na serwerze. Czyli normalnie to działa tak, masz plik na dysku lokalnym lub wymiennym, lub w sieci lokalnej i pobierasz z tego archiwum jakiś plik do pamięci, czyli np. do obiektu typu TMemoryStream, ale pobierasz konkretny plik z archiwum, a nie całe archiwum.

Jak rozumiem Ty chcesz pobrać archiwum z sieci do obiektu typu TMemoryStream, a potem chcesz z tego archiwum znajdującego się w pamięci wyciągnąć plik i przepisać do innego obiektu w pamięci?! Z tego co się orientuję to tak się nie da, gdyż sam kiedyś chciałem zrobić coś podobnego i bez skutku. Archiwa ZIP tego nie obsługują.

Inny sposób to nie wczytywanie do pamięci całego archiwum, a tylko pliku z archiwum. Jest to możliwe, w jednym ze swoich program bazę danych oparłem na tym mechanizmie. Nie działa to jednak dla plików znajdujących się w sieci. Możesz to zrobić tylko w ten sposób, że pobierasz plik z sieci, może być do pamięci, czyli np. do TMemoryStream, ale musisz go zapisać na dysku, a potem pobrać do pamięci plik z tego archiwum.

Nie wiem jak to zrobić dla ZLIB, gdyż używam ZipForge.




Jak pobrać wielkość MemoryStream


Kod: Zaznacz cały
TMemoryStream *mStream = new TMemoryStream();
int size = mStream->Size;


Archiwum znajdujące się w pamięci nie da się dekompresować, gdyż biblioteka ZLIB i chyba żadna inna do obsługi archiwów ZIP, RAR, CAB nie obsługuje takiej operacji. To nie jest kwestia klasy TMemoryStream, gdyż ta klasa wogóle nie obsługuje archiwów, a archiwum ZIP wczytane do pamięci traktuje jak każdy iny plik, to kwestia biblioteki ZLIB i jeżeli ta biblioteka nie ma takiej funkcji to nic nie zrobisz.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dekompresja danych [zlib]

Nowy postprzez Gusław » środa, 30 czerwca 2010, 18:45

Inaczej... Wiedziałem, że zagmatwam.

Używam IdHTTP i ustawiłem w nim Request->AcceptEncoding na: gzip,deflate. Jeśli byłoby ustawienie 'default'owe, czyli nic, to serwer zwraca czysty (nieskompresowany) kod źródłowy strony (html/php). Gdy ustawię tak jak napisałem wyżej, to serwer zwraca kod źródłowy strony w postaci skompresowanej- i o to mi chodzi.

Kod: Zaznacz cały
TStringStream *ODBIERA=new TStringStream("");
...
__try {Form1->IdHTTP1->Get(Form1->IdHTTP1->Response->Location,ODBIERA);} __except (2) {}


Ale ja dostaję te skompresowane źródło w StringStream,a funkcja potrzebuje bodajże bufora w postaci 'char'.
Więc zadam pytanie inaczej, jak można przekonwertować StringStream do char.

Info co do uncompress:
Kod: Zaznacz cały
int uncompress(Bytef *dest, uLongf *destLen, const Bytef*source, uLongf sourceLen);
dest – wskaźnik do bufora do którego zostaną rozpakowane dane
destLen – długość danych rozpakowanych. Wartość zwracana przez funkcje
source – wskaźnik do danych które mają być rozpakowane
sourceLen – długość danych które maja być rozpakowane


Pomieszałem trochę, jak to zwykle. Wybacz Baronie. :roll: ;)
Avatar użytkownika
Gusław
Bladawiec
Bladawiec
 
Posty: 2
Dołączył(a): środa, 30 czerwca 2010, 16:36
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP Home
Kompilator: C++ Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: Dekompresja danych [zlib]

Nowy postprzez Cyfrowy Baron » środa, 30 czerwca 2010, 20:53

Nie mam tej biblioteki mogę więc tylko zgadywać.

Kod: Zaznacz cały

  TMemoryStream 
*mStream = new TMemoryStream();

  // pobierasz dane do mStream

  mStream->Seek(0, soFromBeginning);
  int size = mStream->Size;

 
 Byte[] Bufor = new Byte[size]; //lub char *Bufor = (char*)malloc(size); 
  
   mStream
->Read(Bufor, size); // lub mStream->ReadBuffer(Bufor, size);

 // dalej sam już wiesz
 


Nie sprawdzałem, gdyż nie mam wspomnianej biblioteki
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dekompresja danych [zlib]

Nowy postprzez polymorphism » środa, 30 czerwca 2010, 21:07

Tak jak pokazał Baron, możesz użyć TMemoryStream, z tym że nie musisz kopiować danych z tego strumienia do specjalnie przygotowanego bufora, tylko od razu podać funkcji uncompress wskaźnik zwrócony przez właściwość Memory.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2210
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 206
System operacyjny: Windows 7 Pro
Windows 8.1
Linux Mint 19
Kompilator: Visual Studio 2015 Community
CodeLite (MinGW)
MSYS2 (MinGW, clang)
g++
Gadu Gadu: 0
    Windows XPFirefox

Re: Dekompresja danych [zlib]

Nowy postprzez Darek_C++ » niedziela, 11 lipca 2010, 14:45

@Gusław - jakie biblioteki używasz do tej dekompresji gzip. Skąd ją można pobrać ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Dekompresja danych [zlib]

Nowy postprzez Cyfrowy Baron » niedziela, 11 lipca 2010, 18:10

Darek_C++ napisał(a):@Gusław - jakie biblioteki używasz do tej dekompresji gzip. Skąd ją można pobrać ?


Przecież masz to podane w pierwszym poście i w tytule wątku. Używa biblioteki ZLIB, ale to nie jest komponent.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dekompresja danych [zlib]

Nowy postprzez Darek_C++ » niedziela, 11 lipca 2010, 21:35

Wiem, że to nie jest komponent dlatego też pytam Gustawa "Skąd ją można pobrać ?"
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Dekompresja danych [zlib]

Nowy postprzez Cyfrowy Baron » niedziela, 11 lipca 2010, 21:42

Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 3 gości

cron