2024 11,27 22:42 |
|
2008 12,14 17:05 |
|
WInInet API を使ってサイトのコンテンツをダウンロードしてくる場合、リクエスト情報に Accept-Encoding を付加すると gzip (deflate 圧縮に gz ヘッダー情報がついたもの) されて送られてきます。
圧縮ファイルの解凍ツールは沢山あるのですが、Win32プログラムで使える API があまりありません。 zlib を ダウンロードしてきて zlib.h, zconf.h を StockPrice のプロジェクトに加えて使っています。 最初 uncompress が一番簡単そうに思えたので使ってみたのですが DATAERROR -3 が戻るのみでうまく動きません。受け取ったデータをファイルに全部書き出して "aaa.gz" とか名前を付けてPC上で解凍すると見事に解凍出来ました。データが壊れているわけではなさそうです。 uncompress のソースを読み始めると結局は infalte でゴリゴリ書いてあるだけで、自分で書いても同じ事かなとあきらめかけたのですが、ファイル解凍用の gz_open ではななんと inflateInit2 の windowbits 引数で-MAX_WBITSが指定されている事に気付きました。 注意しないといけないところ、はまるところは inflateInit2 はマクロなので実際に呼ばれている API の inflateInit2_ を GetProcessAddress で呼び込まないといけないことです。 かなり添付ソースでは端折って書いてあります。 まじめに汎用として使うには StockPriceでみているサイトから送られる gz ヘッダーはいつも10バイトなので、10バイトスキップ とかしています。本来は可変長のヘッダーのようですから、例えば該当フラッグビットが1ならそのサイズを取り出してサイズ分コメントを読み飛ばすみたいな事が必要です。 また、複数回にわけて解凍する場合には出力バッファがいっぱいになったら。。。とかコードを入れる必要があります。ここでは1回で解凍していますから端折っています。 いつでも動き始めると簡単でなんで。。。なんで。。。ですが、動くようになるまでが大変です。 全然関係無い話ですが、 昔 Unix のポーティングをしていたときに覚えたのですが、zlib のソースを読んでいて思い出しました。 fopen、fread、fwrite といった f 系の関数に渡すファイルポインタって io_stream 構造体のアドレスなんですね。。。 Unix のソースは読んでいて本当に飽きないですよね。大袈裟ですが人類の英知というか、そうか成程へーっ!みたいな感じです。 ソースです。 /*********************************************************************** // Initialize members to use. zs.next_in = Z_NULL; // Dynamic link "inflateInit2_" szBuf[LoadString(g_hInst, IDS_ERR122, szBuf, MAX_LOADSTRING)] = NULL; // Configure In and Out pointers and the sizes for decompress. // Decompress data. int status = Z_OK; status = inflate(&zs, Z_NO_FLUSH); if ((status == Z_STREAM_END) || (status != Z_OK)) { // Clean up. szBuf[LoadString(g_hInst, IDS_ERR123, szBuf, MAX_LOADSTRING)] = NULL; return FALSE; // The size of expanded size. PR |
|
コメント |
コメント投稿 |
|
trackback |
トラックバックURL |
忍者ブログ [PR] |