sample-gz.c
  1  //
  2  // エラー処理も書いてみたのだが,
  3  // 実際のところ,エラー発生時の動作確認をしていないので,
  4  // 本当にこれでよいのかどうか不安がある.
  5  //
  6  // とりあえず,gzopen,gzclose,gzread,gzwrite は便利だ.
  7  //
  8  
  9  // ファイルを圧縮して出力する
 10  #include    <stdio.h>
 11  #include    <zlib.h>
 12  #include    <errno.h>
 13  
 14  
 15  // 圧縮用のバッファサイズ
 16  #define     BUF_SIZE    ( 1 << 12 )     // 4,096
 17  
 18  
 19  // 入出力用の構造体
 20  typedef     struct CIO
 21  {
 22      FILE    *in;    // 入力
 23      gzFile  out;    // 出力
 24  }   CIO, *hCIO;
 25  
 26  
 27  // 入出力の初期化
 28  static  void    CIO_Init( hCIO h )
 29  {
 30      h->in = NULL;
 31      h->out = NULL;
 32  }
 33  
 34  // 入出力を閉じる
 35  static  int     CIO_Close( hCIO h )
 36  {
 37      int     ret = 0;
 38      const char  *msg;
 39  
 40      // 入力
 41      if ( h->in != NULL )
 42      {
 43          if ( fclose( h->in ) )
 44              perror( "Input" );
 45      }
 46  
 47      // 出力
 48      if ( h->out != NULL )
 49      {
 50          if ( ( ret = gzclose( h->out ) ) == Z_OK )
 51              return  0;
 52  
 53          // エラーメッセージ
 54          msg = gzerror( h->out, &ret );
 55          if ( ret == Z_ERRNO )
 56              perror( "Output" );
 57          else
 58              fprintf( stderr, "Output: %s\n", gzerror( h->out, &ret ) );
 59      }
 60  
 61      return  ret;
 62  }
 63  
 64  // 入出力を開く
 65  static  int     CIO_Open( hCIO h, const char *in, const char *out )
 66  {
 67      CIO_Init( h );
 68  
 69      // 入力を開く
 70      if ( ( h->in = fopen( in, "rb" ) ) == NULL )
 71          perror( in );
 72  
 73      // 出力を閉じる
 74      if ( ( h->out = gzopen( out, "wb" ) ) == NULL )
 75      {
 76          if ( !errno )
 77              fprintf( stderr, "%s: Memory error\n", out );
 78          else
 79              perror( out );
 80      }
 81  
 82      // 面倒なのでまとめてエラー処理
 83      if ( h->in == NULL || h->out == NULL )
 84      {
 85          CIO_Close( h );
 86          return  -1;
 87      }
 88  
 89      return  0;
 90  }
 91  
 92  // 実際に圧縮する
 93  static  int     CIO_Compress( hCIO h )
 94  {
 95      int     ret;
 96      char    buf[ BUF_SIZE ];
 97      size_t  len;
 98      const char  *msg;
 99  
100      // 入力
101      while ( ( len = fread( buf, 1, BUF_SIZE, h->in ) ) > 0 )
102      {
103          // 出力
104          if ( gzwrite( h->out, buf, len ) < len )
105          {
106              // 出力エラー
107              msg = gzerror( h->out, &ret );
108              if ( ret == Z_ERRNO )
109                  perror( "Output" );
110              else
111                  fprintf( stderr, "Output: %s\n", gzerror( h->out, &ret ) );
112          }
113      }
114  
115      // 入力エラー
116      if ( ferror( h->in ) )
117      {
118          perror( "Input" );
119          return  -1;
120      }
121  
122      return  0;
123  }
124  
125  // ファイル in_path を圧縮して,ファイル out_path に出力する
126  int     Compress( const char *in_path, const char *out_path )
127  {
128      int     ret;
129      CIO     io;
130  
131      // 入出力を開く
132      if ( CIO_Open( &io, in_path, out_path ) )
133          return  -1;
134  
135      // 実際に圧縮する
136      ret = CIO_Compress( &io );
137  
138      // 入出力を閉じる
139      if ( !ret )
140          return  CIO_Close( &io );
141      CIO_Close( &io );
142  
143      return  ret;
144  }
145  
146  int     main( int argc, char *argv[] )
147  {
148      if ( argc != 3 )
149      {
150          printf( "Usage: %s Input Output\n", argv[0] );
151          return  1;
152      }
153  
154      return  Compress( argv[1], argv[2] );
155  }