Symbian
Symbian OS Library

FAQ-0844 What support does Symbian OS provide for file compression?

[Index][spacer] [Previous] [Next]



 

Classification: C++ Category: Application Engines
Created: 01/07/2003 Modified: 01/13/2003
Number: FAQ-0844
Platform: Symbian OS v7.0

Question:
What support does Symbian OS provide for compressing and decompressing files?

Answer:
Support is available from Symbian OS v7.0 for decompression of zip files based on a version of the zlib utility. This is accessible through CZipFile and related classes. Although zlib also supports compression, Symbian OS does not provide the necessary extensions to create zip files of the compressed data.

    The following code finds compressed zip files in a folder c:\test\zip and unzips their contents into a c:\test\zip\extracts. Each zip file is unzipped into a subfolder named after the file itself. Note that zip-related errors and other enums are defined in ziparchive.h.

    #include

    _LIT(KExtractZipPath, "C:\\test\\zip\\extracts\\");
    _LIT(KPath, "C:\\test\\zip\\");

    void UnzipFileL(RFs& aFs, TFileName* aFileName);
    void ExtractFileL(RFs& aFs, CZipFileMember* aMember, CZipFile* aZipFile, TFileName* aFileName);
      void DoUnzipL()
        {
        RFs fs;
        User::LeaveIfError(fs.Connect()); //Connect to file session
        User::LeaveIfError(fs.SetSessionPath(KPath)); //Set Session Path to directory containing test zip files
        CleanupClosePushL(fs);
        TFileName path;
        CDir* fileList;
        User::LeaveIfError(fs.GetDir(path, KEntryAttNormal, ESortByName, fileList)); //Get list of files to unzip
        CleanupStack::PushL(fileList);
        for (TInt y = 0; y < fileList->Count(); y++)
          {
          TFileName dirFileName((*fileList)[y].iName);
          UnzipFileL(fs, &dirFileName);
          }CleanupStack::PopAndDestroy(2);
          }

          void UnzipFileL(RFs& aFs, TFileName* aFileName)
            {
            CZipFile* zipFile;
            CZipFileMember* member;
            CZipFileMemberIterator* fileMembers;
            zipFile = CZipFile::NewL(aFs,*aFileName);
            CleanupStack::PushL(zipFile);
            User::LeaveIfError(zipFile->OpenL());
            fileMembers = zipFile->GetMembersL();
            CleanupStack::PushL(fileMembers);
            while (member = fileMembers->NextL())
              {
              //You must take ownership of the member object created for you by NextL()!
              CleanupStack::PushL(member);
              ExtractFileL(aFs, member, zipFile, aFileName);
              aFs.SetSessionPath(KPath);
              CleanupStack::PopAndDestroy(); //member
              }CleanupStack::PopAndDestroy(2); //fileMembers, zipFile
              }
              void ExtractFileL(RFs& aFs, CZipFileMember* aMember, CZipFile* aZipFile, TFileName* aFileName)
                {
                TInt loop=0;
                HBufC* name = aMember->Name()->AllocLC();
                // Change any instances of '/' to '\' in zipped file paths
                while (loop < name->Length())
                  {
                  if ((*name)[loop] == '/')
                    {
                    name->Des()[loop] = '\\';
                    }loop++;
                    }TFileName fn;
                    fn.Append(KExtractZipPath);
                    fn.Append(*aFileName);
                    fn.Append('\\');
                    fn.Append(*name);
                    User::LeaveIfError(aFs.SetSessionPath(KExtractZipPath));
                    TInt err = aFs.MkDirAll(fn));
                    if (err != KErrNone && err != KErrAlreadyExists)
                      {
                      User::Leave(err);
                      }RFile expandedMember;
                      User::LeaveIfError(expandedMember.Replace(aFs, fn, EFileShareAny|EFileWrite));
                      CleanupClosePushL(expandedMember); RZipFileMemberReaderStream* fileStream;
                          // KCompressionMethodNotSupported is possible in decompressing file here User::LeaveIfError(aZipFile->GetInputStreamL(aMember, fileStream));
                          CleanupStack::PushL(fileStream);
                              // Assume file contents are 8-bit data
                              TUint32 size = aMember->UncompressedSize();
                              HBufC8* bytes = HBufC8::NewLC(size);
                              TPtr8 ptr = bytes->Des(); //Obtain a modifiable descriptor
                              fileStream->Read(ptr, size); //Later versions of Symbian use ReadL() instead here
                              // save the unzipped contents to file
                              User::LeaveIfError(expandedMember.Write(ptr));
                              CleanupStack::PopAndDestroy(4); //bytes, fileStream, expandedMember, name
                              }