home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / zkuste / vbasic / Data / Utils / XZipComp.exe / XceedCompression.Cab / F112857_Compress.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-11  |  11.7 KB  |  348 lines

  1. /* Xceed Streaming Compression Library - Compress Sample Application
  2.  * Copyright (c) 2001 Xceed Software Inc.
  3.  *
  4.  * [Compress.cpp]
  5.  *
  6.  * This console application shows how to compress a file, using 
  7.  * different compression data formats. It specifically demonstrates:
  8.  *  - The WriteFile and ProcessFile methods.
  9.  *  - The CompressionFormat property.
  10.  *
  11.  * This file is part of the Xceed Streaming Compression Library sample 
  12.  * applications. The source code in this file is only intended as 
  13.  * a supplement to Xceed Streaming Compression Library's documentation, 
  14.  * and is provided "as is", without warranty of any kind, either 
  15.  * expressed or implied. 
  16.  */
  17.  
  18. #include "stdafx.h"
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <limits.h>
  22. #include "Compress.h"
  23.  
  24. //
  25. // Mapping between command-line and property values
  26. //
  27.  
  28. static SCompressionFormat g_pxCompressionFormats[] = 
  29. {
  30.   { "=Std",     cfStandard },
  31.   { "=BZip2",   cfBZip2 },
  32.   { "=GZip",    cfGZip },
  33.   { "=Zip3",    cfZip3 },
  34.   { "=ZLib",    cfZLib },
  35.   { "=BWT",     cfBWT },
  36.   { "=Deflate", cfDeflate },
  37.   { "=Store",   cfStore },
  38. };
  39.  
  40.  
  41. //--------------------------------------------------------------------------
  42. // Entry point of the application
  43. //--------------------------------------------------------------------------
  44. int main(int argc, char* argv[])
  45. {
  46.   //Initializes the COM library on the current thread following the STA model
  47.   CoInitialize( NULL );
  48.  
  49.   try
  50.   {
  51.     // Create an instance of the XceedStreamingCompression coclass, and
  52.     // use the "I" interface which manipulates byte arrays (instead of
  53.     // Variants for the "D" interfaces).
  54.     IXceedStreamingCompressionPtr piComp;
  55.     piComp.CreateInstance( CLSID_XceedStreamingCompression );
  56.  
  57.     // Two BSTR variables that will contain the Input and Output file names.
  58.     _bstr_t bstrInputFileName;
  59.     _bstr_t bstrOutputFileName;
  60.  
  61.     // Extract the command line parameters and initialize the Compression
  62.     // instance according to the user specification. After this call
  63.     // the Compression instance piComp is ready to compress.
  64.     if( !ExtractParameters( argc, argv, 
  65.                             piComp,
  66.                             bstrInputFileName, 
  67.                             bstrOutputFileName ) )
  68.     {
  69.       ShowHelp();
  70.       return 1;
  71.     }
  72.  
  73.     if( bstrInputFileName.length() == 0 )
  74.     {
  75.       // An input file name was not provided by the user.
  76.       // Get the text to compress from the console
  77.  
  78.       printf( "Compressing the console input. Press Ctrl-Z and Enter when done.\n\n" );
  79.  
  80.       // Make sure to overwrite the file. We first call the WriteFile method without
  81.       // any source data, and with the bAppend parameter set to false.
  82.       DWORD dwBytesWritten = 0;
  83.       piComp->WriteFile( NULL, 0, cfpCompress, FALSE, bstrOutputFileName, FALSE, &dwBytesWritten );
  84.  
  85.       char pcBuffer[ BUFFER_SIZE ];
  86.  
  87.       while( !feof( stdin ) )
  88.       {
  89.         int nRead = fread( pcBuffer, sizeof( char ), BUFFER_SIZE, stdin );
  90.  
  91.         if( nRead )
  92.         {
  93.           // Compress the characters read so far in the output file.
  94.           // We keep calling the WriteFile method with the bEndOfData parameter
  95.           // set to FALSE. This way, all the data we keep feeding the compressor
  96.           // is considered a unique stream of data, and it compresses more.
  97.           piComp->WriteFile( ( BYTE* )pcBuffer, nRead, cfpCompress, FALSE, 
  98.                              bstrOutputFileName, TRUE, &dwBytesWritten );
  99.         }
  100.       }
  101.  
  102.       // Since we always called with bEndOfData to FALSE, the compressor may be
  103.       // holding some more data, so we must make sure to flush the remaining data.
  104.       piComp->WriteFile( NULL, 0, cfpCompress, TRUE, bstrOutputFileName, TRUE, &dwBytesWritten );
  105.  
  106.       printf( "Successfully compressed the console input to file %s\n", ( const char* )bstrOutputFileName );
  107.     }
  108.     else
  109.     {
  110.       // An input file name was provided by the user.
  111.       // Get the text to compress from this file
  112.  
  113.       DWORD dwBytesRead     = 0;
  114.       DWORD dwBytesWritten  = 0;
  115.  
  116.       // Compress by reading a file and sending the output to another file.
  117.       // We simply call the ProcessFile method once, providing:
  118.       //  - The source filename, without any offset or size, since we want to
  119.       //    compress it all.
  120.       //  - The type of processing we want to perform, in this case cfpCompress.
  121.       //  - This is our last (and first!) call to the method, so bEndOfData is
  122.       //    FALSE.
  123.       //  - The destination filename, with the bAppend parameter set to FALSE,
  124.       //    since we want to overwrite any existing file.
  125.       //  - The address of two DWORD which will contain the number of bytes
  126.       //    read and written on return.
  127.       piComp->ProcessFile( bstrInputFileName, 0, 0, cfpCompress, TRUE, 
  128.                            bstrOutputFileName, FALSE, 
  129.                            &dwBytesRead, &dwBytesWritten );
  130.  
  131.       printf( "Successfully compressed file %s [%d] to file %s [%d]\n", 
  132.               ( const char* )bstrInputFileName, dwBytesRead, 
  133.               ( const char* )bstrOutputFileName, dwBytesWritten );
  134.     }
  135.   }
  136.   catch( const _com_error& err )
  137.   {
  138.     // When using the "#import" directive, the compiler generates wrapper classes
  139.     // around all interface types. These wrapper classes throw exceptions when
  140.     // a method call returns an HRESULT which is a failure code.
  141.     printf( "Error %08x: %s\n", err.Error(), ( const char* )err.Description() );
  142.   }
  143.   catch( ... )
  144.   {
  145.     // Catch any other exception.
  146.     printf( "An unknown error occured.\n" );
  147.   }
  148.  
  149.   // Close the COM library for the current thread
  150.   CoUninitialize();
  151.  
  152.   return 0;
  153. }
  154.  
  155. //--------------------------------------------------------------------------
  156. // Display usage information
  157. //--------------------------------------------------------------------------
  158. void ShowHelp()
  159. {
  160.   //      "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
  161.   printf( "Usage: Compress [options] [input_file] output_file\n\n"
  162.           "  input_file: the file to compress\n"
  163.           "  output_file: the destination file\n\n"
  164.           "  options: /m=[Std | BZip2 | GZip | Zip3 | ZLib | BWT | Deflate | Store]\n"
  165.           "              This is the compression format. The default is 'Std'\n"
  166.           "           /h or /? : Show this help\n" );
  167. }
  168.  
  169. //--------------------------------------------------------------------------
  170. // Extract commands from the command line parameters
  171. //
  172. // In this function, we call the piComp interface and let exceptions
  173. // be caught by the caller.
  174. // This function returns false if an error occured parsing the command
  175. // line parameters or if the user requested help.
  176. //--------------------------------------------------------------------------
  177. bool ExtractParameters( int argc, char* argv[],
  178.                         IXceedStreamingCompressionPtr piComp, 
  179.                         _bstr_t& bstrInputFileName,
  180.                         _bstr_t& bstrOutputFileName )
  181. {
  182.   // We set pxFormat to the first compression format of the global 
  183.   // compression format array in case the user don't specify any.
  184.   SCompressionFormat*  pxFormat = g_pxCompressionFormats;
  185.   bool bFound;
  186.  
  187.   int   i = 0;
  188.  
  189.   // We parse each command line parameter
  190.   while( ++i < argc )
  191.   {
  192.     if( argv[ i ][ 0 ] == '/' )
  193.     {
  194.       // The parameter starts with a /
  195.       // Meaning it's an option parameter
  196.       switch( argv[ i ][ 1 ] )
  197.       {
  198.         case 'm':
  199.         case 'M':
  200.           // The user wants to set the compression method
  201.           bFound = false;
  202.  
  203.           // We go through all the compression methods in the 
  204.           // correspondence table, stopping when we find a 
  205.           // match.
  206.           for( pxFormat = g_pxCompressionFormats;
  207.                pxFormat->pszCommandLine != NULL;
  208.                pxFormat++ )
  209.           {
  210.             if( lstrcmpi( argv[ i ] + 2, pxFormat->pszCommandLine ) == 0 )
  211.             {
  212.               bFound = true;
  213.               break;
  214.             }
  215.           }
  216.  
  217.           if( !bFound )
  218.           {
  219.             printf( "Invalid compression format '%s'\n\n", argv[ i ] );
  220.             return false;
  221.           }
  222.  
  223.           break;
  224.  
  225.         default:
  226.           printf( "Unknown command '%s'\n\n", argv[ i ] );
  227.           // Continue
  228.         case 'h':
  229.         case 'H':
  230.         case '?':
  231.           return false;
  232.       }
  233.     }
  234.   }
  235.  
  236.   if( argc < 2 || argv[ argc - 1 ][ 0 ] == '/' )
  237.   {
  238.     printf( "You did not specify an output filename\n\n" );
  239.     return false;
  240.   }
  241.   else if( argc < 3 || argv[ argc - 2 ][ 0 ] == '/' )
  242.   {
  243.     // Only an output file was specified
  244.     bstrOutputFileName = argv[ argc - 1 ];
  245.   }
  246.   else
  247.   {
  248.     // Both input and output file were specified
  249.     bstrInputFileName   = argv[ argc - 2 ];
  250.     bstrOutputFileName  = argv[ argc - 1 ];
  251.   }
  252.  
  253.   // Set the compression format property of the piComp.
  254.   //  - We create the corresponding format instance.
  255.   //  - We optionally set its properties (none in this sample).
  256.   //  - We assign it to the CompressionFormat property of the main
  257.   //    compression object. Since this property is of type
  258.   //    "IXceedCompressData*", we use the wrapper class to perform
  259.   //    a QueryInterface on our format instance.
  260.  
  261.   switch( pxFormat->eFormat )
  262.   {
  263.     case cfBZip2 :
  264.     {
  265.       IXceedBZip2CompressionFormatPtr piFormat;
  266.       
  267.       piFormat.CreateInstance( CLSID_XceedBZip2CompressionFormat );
  268.       piComp->CompressionFormat = IXceedCompressDataPtr( piFormat );
  269.     }
  270.     break;
  271.  
  272.     case cfGZip :
  273.     {
  274.       IXceedGZipCompressionFormatPtr piFormat;
  275.       
  276.       piFormat.CreateInstance( CLSID_XceedGZipCompressionFormat );
  277.       piComp->CompressionFormat = IXceedCompressDataPtr( piFormat );
  278.     }
  279.     break;
  280.  
  281.     case cfStandard :
  282.     {
  283.       IXceedStandardCompressionFormatPtr piFormat;
  284.       
  285.       piFormat.CreateInstance( CLSID_XceedStandardCompressionFormat );
  286.       piComp->CompressionFormat = IXceedCompressDataPtr( piFormat );
  287.     }
  288.     break;
  289.  
  290.     case cfZip3 :
  291.     {
  292.       IXceedZip3CompressionFormatPtr piFormat;
  293.       
  294.       piFormat.CreateInstance( CLSID_XceedZip3CompressionFormat );
  295.       piComp->CompressionFormat = IXceedCompressDataPtr( piFormat );
  296.     }
  297.  
  298.     case cfZLib :
  299.     {
  300.       IXceedZLibCompressionFormatPtr piFormat;
  301.       
  302.       piFormat.CreateInstance( CLSID_XceedZLibCompressionFormat );
  303.       piComp->CompressionFormat = IXceedCompressDataPtr( piFormat );
  304.     }
  305.     break;
  306.  
  307.     // The next three items are not compression formats. They are compression
  308.     // methods. They still can be assigned to the CompressionFormat property 
  309.     // of the XceedStreamingCompression object. In this case, the resulting
  310.     // compressed streams will have no formating (no header, footer, checksum, ...)
  311.     case cfBWT :
  312.     {
  313.       IXceedBWTCompressionMethodPtr piMethod;
  314.       
  315.       piMethod.CreateInstance( CLSID_XceedBWTCompressionMethod );
  316.       piComp->CompressionFormat = IXceedCompressDataPtr( piMethod );
  317.     }
  318.     break;
  319.  
  320.     case cfDeflate :
  321.     {
  322.       IXceedDeflateCompressionMethodPtr piMethod;
  323.       
  324.       piMethod.CreateInstance( CLSID_XceedDeflateCompressionMethod );
  325.       piComp->CompressionFormat = IXceedCompressDataPtr( piMethod );
  326.     }
  327.     break;
  328.  
  329.     case cfStore :
  330.     {
  331.       // Using Store as the compression format will produce an output
  332.       // compressed stream identical to the source to compress!
  333.       IXceedStoreCompressionMethodPtr piMethod;
  334.       
  335.       piMethod.CreateInstance( CLSID_XceedStoreCompressionMethod );
  336.       piComp->CompressionFormat = IXceedCompressDataPtr( piMethod );
  337.     }
  338.     break;
  339.   }
  340.  
  341.   return true;
  342. }
  343.  
  344.  
  345. //
  346. // END_OF_FILE
  347. //
  348.