Pagina 1 di 1

[zlib , C++] estrarre file .gz

Inviato: venerdì 16 maggio 2014, 17:23
da andreafioraldi
Ciao a tutti,
ho la necessità di leggere e decomprimere un file gz e poi assegnare il contenuto decompresso a una stringa (buf).
attualmente sto usando questo codice , ma la stringa finale contiene un risultato parziale , non tutto il file gz viene decompresso.
(ad esempio se il file decompresso dovrebbere contenere la stringa "ciao a tutti" , buf contiene solo "ciao a")

Codice: Seleziona tutto

void Extract(string path,string dir )
{
string buf;
gzFile  file;
file = gzopen ( path.c_str() , "r");
if (! file) 
{
        cerr << "gzip error: " << path << ": " << strerror(errno) << "\n";
        exit(1);
}
while (1) {
        int err;                    
        int bytes_read;
        unsigned char buffer[LENGTH];
        bytes_read = gzread (file, buffer, LENGTH - 1);
        buffer[bytes_read] = '\0';
	buf += (char*)buffer;
	if (bytes_read < LENGTH - 1) 
	{
		if (gzeof (file)) {
			break;
		}
		else {
			const char * error_string;
			error_string = gzerror (file, & err);
			if (err) {
				cerr << "error: " << error_string << "\n";
				exit(1);
			}
		}
	}
}
gzclose (file);

Bfa P;
P.Set(buf);
P.Extract(dir);
}
qualcuno che è esperto con zlib sà come aiutarmi? grazie.

Re: [zlib , C++] estrarre file .gz

Inviato: sabato 17 maggio 2014, 11:13
da ixamit
Ci sono delle incongruenze nel tuo codice... forse hai copiato qualcosa di vecchio.
1) gzFile e' definito diversamente nella nuova zlib.

Codice: Seleziona tutto

 grep -m 1 gzFile /usr/include/zlib.h
 typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
[/s]EDIT: svista mia, non e' il tuo caso. Tanti errori sul web presenti sulla definizione

2) leggi l'header:
/usr/include/zlib.h ha scritto: /*
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));

Opens a gzip (.gz) file for reading or writing. The mode parameter is as
in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
for fixed code compression as in "wb9F". (See the description of
deflateInit2 for more information about the strategy parameter.) 'T' will
request transparent writing or appending with no compression and not using
the gzip format.

"a" can be used instead of "w" to request that the gzip stream that will
be written be appended to the file. "+" will result in an error, since
reading and writing to the same gzip file is not supported. The addition of
"x" when writing will create the file exclusively, which fails if the file
already exists. On systems that support it, the addition of "e" when
reading or writing will set the flag to close the file on an execve() call.

These functions, as well as gzip, will read and decode a sequence of gzip
streams in a file. The append function of gzopen() can be used to create
such a file. (Also see gzflush() for another way to do this.) When
appending, gzopen does not test whether the file begins with a gzip stream,
nor does it look for the end of the gzip streams to begin appending. gzopen
will simply append a gzip stream to the existing file.

gzopen can be used to read a file which is not in gzip format; in this
case gzread will directly read from the file without decompression. When
reading, this will be detected automatically by looking for the magic two-
byte gzip header.

gzopen returns NULL if the file could not be opened, if there was
insufficient memory to allocate the gzFile state, or if an invalid mode was
specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
errno can be checked to determine if the reason gzopen failed was that the
file could not be opened.
*/

Re: [zlib , C++] estrarre file .gz

Inviato: sabato 17 maggio 2014, 19:28
da andreafioraldi
Alla fine ho risolto usando z_stream e non gzFile.
se a qualcuno potrebbe essere utile posto la funzione in cui decomprimo una stringa:

Codice: Seleziona tutto

void Extract(string path)
{

string dir = vard + "/processing";
string fp = fileLoad(path);

z_stream S;
memset(&S, 0, sizeof(S));

if ( inflateInit2(&S, 16+MAX_WBITS) != Z_OK)
	cerr << "gzip error: " << strerror(errno) << "\n";

S.next_in = (unsigned char*)fp.data();
S.avail_in = fp.size();

char _read[32768];
string buf;
int RES;

do 
{
	S.next_out = (unsigned char*)_read;
	S.avail_out = sizeof(_read);

	RES = inflate(&S, 0);

	if (buf.size() < S.total_out) 
	{
		buf.append(_read,
		S.total_out - buf.size());
        }

} 
while (RES == Z_OK);

inflateEnd(&S);

if (RES != Z_STREAM_END) 
	cerr << "gzip error: " << RES << ": " << S.msg << "\n";

Bfa P;
P.Set(buf);
P.Extract(dir);

}
Ciao :-)