• Advertisement
Sign in to follow this  

Problems with ZLIB

This topic is 4616 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to create a data compresser for a PAK file like system, nicknamed Big Data Files (Hence the BDF Header ;) ). The problem is, whenever i try to extract, i keep gettin Z_DATA_ERROR from the uncompress function. the source for the compressor and extractor are below:
// BDF Creator.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

using namespace std;
using namespace boost;

int main(int argc, char* argv[])
{
	try
	{
		//
		using namespace boost::filesystem;
		cout << "BDF Creator\n";
		path Source(argv[1]);
		if(!exists(Source))
		{
			cout << "Error: Cannot find source directory! Aborting...\n";
			return -1;
		}
		//To Support huge output files expected
		//we will write a temp output file on the fly as we go.
		vector<ix_BDFFileLocationData> FileData;
		directory_iterator end_itr; // default construction yields past-the-end
		//Get the number of files
		uint32 FileNum = 0;
		vector<string> FileName;
		for(directory_iterator itr(Source); itr != end_itr; ++itr)
		{
			FileName.push_back(itr->leaf());
			++FileNum;
		}
		cout << FileNum << " Files Found, Processing...\n";
		//sort the list
		sort(FileName.begin(), FileName.end());
		vector<string> FilePath(FileNum);
		for(unsigned int i = 0; i < FileNum; i++)
		{
			FilePath = argv[1] + FileName;
		}
		//create the intermediate temp output
		ofstream Temp("bdfcreate.tmp", ios::binary);
		int NextOffset = 0;
		for(unsigned int i = 0; i < FileNum; i++)
		{
			ix_BDFFileLocationData TempData;
			TempData.Filename = FileName;
			TempData.UnpackedSize = uint32(file_size(FilePath));
			TempData.Offset = NextOffset;
			//Pack it and get the packed size
			//prepare the buffers
			unsigned int DestSize = unsigned int(TempData.UnpackedSize + (TempData.UnpackedSize * 0.1f) + 12);
			Bytef* src = new Bytef[TempData.UnpackedSize];
			Bytef* dst = new Bytef[DestSize];
			//copy the source file into the buffer
			std::ifstream SourceFile(FilePath.c_str() , ios::binary);
			SourceFile.read((char*)src, TempData.UnpackedSize);
			SourceFile.close();
			//compress it into the dest
			uLongf DLen = DestSize;
			uLong SLen = TempData.UnpackedSize;
			int CompressionResult = compress(dst, &DLen, src, SLen);
			//error checking
			if(CompressionResult != Z_OK)
			{
				cout << "Compression Error In File " << TempData.Filename << " :\n";
				if(CompressionResult == Z_MEM_ERROR)
				{
					cout << "\tNot Enough Memory.\n";
				}
				if(CompressionResult == Z_BUF_ERROR)
				{
					cout << "\tBuffer Error: Please Report.\n";
				}
				return -2;
			}
			//free the source buffer, no longer needed
			delete [] src;
			//Check for the rare case that a compressed file is greater than the uncompressed file
			//issue a warning, but continue.
			if(DLen > SLen)
			{
				cout << "Warning: File " << TempData.Filename << " Expanded Under Compression.\n";
			}
			//copy the packed size into the temp data
			TempData.PackedSize = DLen;
			//append the dest to the temp file
			Temp.write((char*)dst, DLen);
			//Free The destination buffer
			delete [] dst;
			//add the packed size to the next offset
			NextOffset += DLen;
			//Add the temp data to the data list
			FileData.push_back(TempData);
		}
		Temp.close();
		//output the bdf file
		const char* HDR = "BDFV1";
		uint32 Version = 0;
		uint32 TI;
		ofstream Output(argv[2], ios::binary);
		//Header
		Output.write(HDR, 5);
		Output.write((char*)&Version, sizeof(uint32));
		TI = 0; //Flags
		Output.write((char*)&TI, sizeof(uint32));
		//RealOffset
		uint32 OffsetBeginning = 21; //Initial Size
		//calc the file index difference
		for(unsigned int i  = 0; i < FileData.size(); i++)
		{
			OffsetBeginning += 17 + FileData.Filename.size();
		}
		Output.write((char*)&OffsetBeginning, sizeof(uint32));
		Output.write((char*)&FileNum, sizeof(uint32));
		//write the file data list
		for(unsigned int i = 0; i < FileData.size(); i++)
		{
			TI = uint32(FileData.Filename.size() + 1);
			Output.write((char*)&TI, sizeof(uint32));
			Output.write(FileData.Filename.c_str(), TI);
			Output.write((char*)&FileData.Offset, sizeof(uint32));
			Output.write((char*)&FileData.PackedSize, sizeof(uint32));
			Output.write((char*)&FileData.UnpackedSize, sizeof(uint32));
		}
		//now append the compiled binary temp file into this
		ifstream AppendFile("bdfcreate.tmp" , ios::binary);
		unsigned int AppendSize = unsigned int(file_size("bdfcreate.tmp"));
		byte* TempData = new byte [AppendSize];
		//read the data
		AppendFile.read((char*)TempData, AppendSize);
		//close the file
		AppendFile.close();
		//write the data
		Output.write((char*)TempData, AppendSize);
		//close the output
		Output.close();
		//delete  the buffer
		delete [] TempData;
		//delete the temp output file
		if(remove("bdfcreate.tmp"))
		{
			cout << "Error: Couldn't Delete Temporary Intermediate File bdfcreate.tmp\n";
			return -3;
		}
		return 0;
	}
	catch(std::exception& e)
	{
		cout << "Exception Thrown:\n";
		cout << "\t" << e.what();
		return -65536;
	}
}
// BDF Extractor.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

using namespace std;

int main(int argc, char* argv[])
{
	try
	{
		cout << "Extracting BDF File " << argv[1] << " To " << argv[2] << " ...\n";
		ifstream Input(argv[1]);
		char HDR[5];
		Input.read(HDR, 5);
		if(!(HDR[0] == 'B' &&
			 HDR[1] == 'D' &&
			 HDR[2] == 'F' &&
			 HDR[3] == 'V' &&
			 HDR[4] == '1'))
		{
			cout << "Not A BDF File (Bad Header)!\n";
			Input.close();
			return -1;
		}
		uint32 TI;
		//Version
		Input.read((char*)&TI, sizeof(uint32));
		//Flags
		Input.read((char*)&TI, sizeof(uint32));
		//Offset
		Input.read((char*)&TI, sizeof(uint32));
		//Number Of Files
		uint32 FileNum;
		Input.read((char*)&FileNum, sizeof(uint32));
		//Read The File Data
		vector<ix_BDFFileLocationData> FileData(FileNum);
		for(unsigned int i = 0; i < FileNum; i++)
		{
			ix_BDFFileLocationData TempData;
			Input.read((char*)&TI, sizeof(uint32));
			char* TC = new char [TI];
			Input.read(TC, TI);
			TempData.Filename = TC;
			delete [] TC;
			Input.read((char*)&TempData.Offset, sizeof(uint32));
			Input.read((char*)&TempData.PackedSize, sizeof(uint32));
			Input.read((char*)&TempData.UnpackedSize, sizeof(uint32));
			FileData = TempData; //won't push back coz I already know the number
			//Saving me having to resize the vector everytime.
		}
		//Now Begin The Extraction
		for(unsigned int i = 0; i < FileNum; i++)
		{
			string FullPath(argv[2]);
			FullPath += FileData.Filename;
			Bytef* src = new Bytef [FileData.PackedSize];
			Bytef* dst = new Bytef [FileData.UnpackedSize];
			Input.read((char*)src, FileData.PackedSize);
			//deflate
			uLongf SLen = FileData.PackedSize, DLen = FileData.UnpackedSize;
			int CompressionResult = uncompress(dst, &DLen, src, SLen);
			//error checking
			if(CompressionResult != Z_OK)
			{
				cout << "Decompression Error In File " << FileData.Filename << " :\n";
				if(CompressionResult == Z_MEM_ERROR)
				{
					cout << "\tNot Enough Memory.\n";
				}
				if(CompressionResult == Z_BUF_ERROR)
				{
					cout << "\tBuffer Error: Please Report.\n";
				}
				if(CompressionResult == Z_DATA_ERROR)
				{
					cout << "\tCorrupt Data\n";
				}
				//return -2;
			}
			//delete the src
			delete [] src;
			//write the dest
			ofstream Output(FullPath.c_str(), ios::binary);
			Output.write((char*)dst, DLen);
			Output.close();
			//delete it
			delete [] dst;
		}
		Input.close();
		return 0;
	}
	catch(std::exception& e)
	{
		cout << "Exception Thrown:\n";
		cout << "\t" << e.what();
		return -65536;
	}
}

Any help would be appreciated...

Share this post


Link to post
Share on other sites
Advertisement
I don't think anyone will ever read through all that, not me at least.

However, check manually using the debugger that you are reading from the same position (check e.g. the first 4 bytes of zipped data, and then when you read and make sure it is the same).

EDIT: btw, I think the 4-6 first are ALWAYS the same when compressing with zlib.

Share this post


Link to post
Share on other sites
Rather than read though all that code [wink], take a look at the source of my SimpleArchive project, which does basically what you have described. I used this page as my reference for making the library. It works fine both ways, so you can start comparing code (mines heavily commented) so you can get a better idea of what you need to aim for. Good luck!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement