tags:

views:

486

answers:

2

I am trying to use the LZMA SDK to create a zip archive (either .zip or .7z format). I've downloaded and built the SDK and I just want to use the dll exports to compress or decompress a few files. When I use the LzamCompress method, it returns 0 (SZ_OK) as if it worked correctly. However, after I write the buffer to file and try to open it, I get an error that the file cannot be opened as an archive.

Here is the code I am currently using. Any suggestions would be appreciated.

#include "lzmalib.h"

typedef unsigned char byte;

using namespace std;

int main()
{
    int length = 0;
    char *inBuffer;

    byte *outBuffer = 0;
    size_t outSize;
    size_t outPropsSize = 5;
    byte * outProps = new byte[outPropsSize];

    fstream in;
    fstream out;

    in.open("c:\\temp\\test.exe", ios::in | ios::binary);

    in.seekg(0, ios::end);
    length = in.tellg();
    in.seekg(0, ios::beg);

    inBuffer = new char[length];

    outSize = (size_t) length / 20 * 21 + ( 1 << 16 ); //allocate 105% of file size for destination buffer

    if(outSize != 0)
    {
     outBuffer = (byte*)malloc((size_t)outSize);
     if(outBuffer == 0)
     {
      cout << "can't allocate output buffer" << endl;
      exit(1);
     }
    }

    in.read(inBuffer, length);
    in.close();

    int ret = LzmaCompress(
     outBuffer, /* output buffer */
     &outSize, /* output buffer size */
     reinterpret_cast<byte*>(inBuffer),/* input buffer */
     length, /* input buffer size */
     outProps, /* archive properties out buffer */
     &outPropsSize,/* archive properties out buffer size */
     5, /* compression level, 5 is default */
     1<<24,/* dictionary size, 16MB is default */
     -1, -1, -1, -1, -1/* -1 means use default options for remaining arguments */
    );

    if(ret != SZ_OK)
    {
     cout << "There was an error creating the archive." << endl;
     exit(1);
    }

    out.open("test.zip", ios::out | ios::binary);

    out.write(reinterpret_cast<char*>(outBuffer), (int)(outSize));
    out.close();

    delete inBuffer;
    delete outBuffer;
}
A: 

I do not know about LZMA specifically, but from what I know of compression in general, it looks like you are writing a compressed bit stream to a file without any header information that would let a decompression program know how the bit stream is compressed.

The LzmaCompress() function probably writes this information to outProps. There should be another function in the SDK that will take the compressed bit stream in outBuffer and the properties in outProps and create a proper archive from them.

Dan Hook
That's kind of what I'm thinking, but the dll only exports LzmaCompress and LzmaDecompress.
scottm
If you could decompress it with LzmaDecompress, would that solve your problem or do you have to generate an archive compatible with 7zip?
Dan Hook
I supposed decompressing with LzmaDecompress would be fine, but when I try that, the output size remains 0, even though the function returns SZ_OK
scottm
I've done this, some years ago, using zlib. I had to write all the PKZIP meta-info myself, zlib just produced the deflated file data. Obviously this is different tools, but LZMA is a compression algorithm, not an archive format. So my expectation of a function called LzmaCompress is that it would not produce an archive file, just some compressed data. 7zip files start with the two bytes '7', 'z', and PKZIP with 'P', 'K', '\03', '\04'. If you're not seeing those, it ain't an archive. At least not in either of the formats you want.
Steve Jessop
A: 

i am also trying to do this but still not successful. some points to be noted..

1) the intial 5 bytes will be the header properties (outProps) and the next 8 bytes is the length .

2) Then comes the compressed data.

When i write in this way also it fails.

i think we need to add '7' , 'z' also . i am not sure.

kiran
I gave up and wrote a class to interface with 7zip.exe :(
scottm