ファイル圧縮について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
にこよん
記事: 112
登録日時: 2年前
住所: 大阪府
連絡を取る:

ファイル圧縮について

#1

投稿記事 by にこよん » 2年前

前回(http://dixq.net/forum/viewtopic.php?f=3&t=19394)ファイル圧縮について教えていただいたのですが、
途中でスレッドを終了させて、あの後しばらく調べたので再度質問しに来ました。

とりあえず仮のデータ

コード:

static int test[20];
static int test2[40];
この二つを圧縮してファイルに書き込む処理を書きたいです。

そしてソースを書いてみたのですが(一番下)いくつかどうすればいいのかわからなかった所をご教示願います。

zlibのインストールの方法が分からなかったのでとりあえず公式からダウンロードしたファイルから
"zlib.h"と"zconf.h"の二つのファイルだけコピーしてプロジェクトに追加し、そのままインクルードしたのですが、
ちゃんと使うにはどうすればいいのでしょうか?

一応説明で「ブラウザや wget により tarball をダウンロードした後は,configure, make, make check, make install という一般的な手順でインストールします」というのは読んだのですが全く意味が分かりません。
zlib を軽く試してみるのであれば,make check まで終わった時点で,zlib.h, zconf.h, libz.a のみをコピーして使うことも可能です.」とも書いていたのですがlibz.aは見つからず、「make check まで終わった時点で
というのも分からないのでとりあえず"zlib.h"と"zconf.h"の二つのファイルだけコピーしてプロジェクトに追加した次第です。


そして正しくインストールできていないからなのか下の様なエラーメッセージが出てしまいます。

重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー LNK2019 未解決の外部シンボル _compress2 が関数 _main で参照されました。 ファイル圧縮 C:\Users\ユーザーファイル\Documents\Visual Studio 2017\Projects\ファイル圧縮\ファイル圧縮\main.obj 1



コード:


#include "zlib.h"
#include "zconf.h"
#include <stdio.h>
#include <Windows.h>
#include <iostream>
#include <string>

static int test[20];
static int test2[40];

int main() {
	unsigned char *buffer = (unsigned char*)malloc(64 * 1024 * 1024);  // 保存するデータより十分大きいメモリを確保
	int size = 0;

	//メモリに書き込み
	memcpy(buffer + size, &test, sizeof(int) * 20);
	size += sizeof(int) * 20;

	//メモリに書き込み
	memcpy(buffer + size, &test2, sizeof(int) * 40);
	size += sizeof(int) * 40;

	unsigned char *press_buffer = (unsigned char*)malloc(64 * 1024 * 1024); // 圧縮データより十分大きいメモリを確保
	int press_size;


	Bytef *press_buffer2 = (Bytef*)malloc(64 * 1024 * 1024); // 圧縮データより十分大きいメモリを確保
	uLong press_size2;

	//~~~~~~~~~~~~~~~~~~~~~~~~~
	//	buffer のデータを圧縮して press_buffer に格納、圧縮後のデータサイズを press_size に格納する処理
	//~~~~~~~~~~~~~~~~~~~~~~~~~
	compress2(press_buffer, &press_size2, buffer, uLong(sizeof(buffer)), Z_BEST_COMPRESSION);				//圧縮

	FILE *fp;
	errno_t err;

	err = fopen_s(&fp, "data.sav", "wb");		//書き込みでファイルを開く	fwrite(&fh, sizeof(file_header_t), 1, fp);			//ファイルのヘッダ情報

	// 圧縮データのサイズを書き出し
	fwrite(&press_size, sizeof(int), 1, fp);

	// 圧縮データを書き出し
	fwrite(press_buffer, press_size, 1, fp);

	fclose(fp);											//ファイルを閉じる

														// 確保したメモリの解放
	free(buffer);
	free(press_buffer);


	Sleep(10000);
	return 0;
}
最近は東方風アクションゲームを少しずつ作ってる人です
東方翠風燐FreeDownload⇒http://dxlib.o.oo7.jp/cgi/patio/read.cgi?no=212

Tepp
記事: 13
登録日時: 3年前
住所: フォッサマグナ
連絡を取る:

Re: ファイル圧縮について

#2

投稿記事 by Tepp » 2年前

まず、大前提としてZlibはオープンソースソフトウェアで自分でビルドする必要があります。
(前スレッドでzlibvc.slnでビルドしているので理解していると思いますが)

ビルドすると、ライブラリファイルであるzlibstat.libが出来ます。
これがREADMEにおけるlibz.aと同等です。
そしてできたこのライブラリファイルを自プロジェクトにリンクされるように設定して下さい。
オフトピック
ライブラリファイルはlinux系だと.a、windows(VS)だと.libであることが多いです。
zlibstat.libのstatは多分staticの略。
にこよん さんが書きました:エラー LNK2019 未解決の外部シンボル _compress2 が関数 _main で参照されました。
は「_compress2関数 の宣言あるけど、定義がないよ!」というエラーです。
_compress2関数はzlibの関数でzlibのヘッダーファイルにて宣言されていますが、
その定義はzlibstat.libの中にあるのでちゃんとライブラリファイルを設定すればこのエラーはなくなります。

そもそもライブラリへの理解が怪しいようであれば、
まずはそこから調べて知識を固めるのが良いかと思います。

アバター
にこよん
記事: 112
登録日時: 2年前
住所: 大阪府
連絡を取る:

Re: ファイル圧縮について

#3

投稿記事 by にこよん » 2年前

Tepp さんが書きました: ビルドすると、ライブラリファイルであるzlibstat.libが出来ます。
これがREADMEにおけるlibz.aと同等です。
そしてできたこのライブラリファイルを自プロジェクトにリンクされるように設定して下さい。
zlibstat.libをリンクしないといけないのですね...
ありがとうございます。


zlibstat.libが入っているフォルダのパスを追加のライブラリディレクトリに追加し、
プログラム内で

コード:

#pragma comment(lib, "C:\\library\\zlib\\zlibstat.lib")
と、書いてみたり追加の依存ファイルにzlibstat.lib;を追加したりしてみたのですが、
相変わらずエラーが出てしまいます。
リンクの方法が間違っているのでしょうか?
重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
警告 MSB8030 リンカー スイッチ "Minimum Required Version" では、"SubSystem" を設定する必要があります。"SubSystem" を設定しないと、"Minimum Required Version" がリンカーに渡されないため、出力バイナリを古いオペレーティング システムで実行できません。 ファイル圧縮 C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.CppBuild.targets 1202
最近は東方風アクションゲームを少しずつ作ってる人です
東方翠風燐FreeDownload⇒http://dxlib.o.oo7.jp/cgi/patio/read.cgi?no=212

Tepp
記事: 13
登録日時: 3年前
住所: フォッサマグナ
連絡を取る:

Re: ファイル圧縮について

#4

投稿記事 by Tepp » 2年前

にこよん さんが書きました:警告 MSB8030
メッセージに書いてあるように、サブシステムが設定されなていないみたいなので設定してください。
プロジェクトのプロパティ->構成プロパティ->リンカ->システム->サブシステム
コンソールなら「コンソール」、win32プロジェクトなら「Windows」が適当かと思います。
(少なくともVSで各々のプロジェクト作ったらそうなります)
オフトピック
プロジェクトに依存関係のファイルを設定していれば、#pragma~はいりません。逆もまた然り。
オフトピック
エラー番号、メッセージでググれば、大抵誰かが同じエラー出しているので、すぐに答えが見つかります。

アバター
にこよん
記事: 112
登録日時: 2年前
住所: 大阪府
連絡を取る:

Re: ファイル圧縮について

#5

投稿記事 by にこよん » 2年前

Tepp さんが書きました:メッセージに書いてあるように、サブシステムが設定されなていないみたいなので設定してください。
プロジェクトのプロパティ->構成プロパティ->リンカ->システム->サブシステム
コンソールなら「コンソール」、win32プロジェクトなら「Windows」が適当かと思います。
(少なくともVSで各々のプロジェクト作ったらそうなります)
ありがとうございます。これで警告は消えたのですが、書き方が悪かったです。
上の警告も増えたのですが、警告だけでなく最初に書いたエラーが消えなかったのです。(↓)

重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー LNK2019 未解決の外部シンボル _compress2 が関数 _main で参照されました。 ファイル圧縮 C:\Users\ユーザー\Documents\Visual Studio 2017\Projects\ファイル圧縮\ファイル圧縮\main.obj 1
エラー LNK1120 1 件の未解決の外部参照 ファイル圧縮 C:\Users\ユーザー\Documents\Visual Studio 2017\Projects\ファイル圧縮\Debug\ファイル圧縮.exe 1


なのでリンクの方法が間違えているのかなと。

Tepp さんが書きました:プロジェクトに依存関係のファイルを設定していれば、#pragma~はいりません。逆もまた然り。
片方だけにしてみたりしたのですがダメでした。
最近は東方風アクションゲームを少しずつ作ってる人です
東方翠風燐FreeDownload⇒http://dxlib.o.oo7.jp/cgi/patio/read.cgi?no=212

アバター
にこよん
記事: 112
登録日時: 2年前
住所: 大阪府
連絡を取る:

Re: ファイル圧縮について

#6

投稿記事 by にこよん » 2年前

前スレッドで教えていただいたzLib.libを同じ方法でリンクしたら無事エラーが起きることなくコンパイルできました。

Teppさん、そして前スレッドで沢山のことを教えていただいた皆様、ありがとうございました。

圧縮してファイルに書き出したり、ファイルから読み込んで展開したりすることにも成功したので、
今後同じことで悩んだ人のために残しておきます。(すごく汚いテストコードですが...)

間違った書き方をしていたり、もっとこういう書き方したほうがいいよとかアドバイスがあればご教示ください。

コード:


#pragma comment(lib, "Zlib.lib")		//Zlibをリンクする

#include <zlib.h>						//Zlibをインクルードする
#include <stdio.h>
#include <Windows.h>
#include <iostream>
#include <string>

int Pressure();		//圧縮してファイルに保存する
int Expansion();	//ファイルから読み込んで展開する


int main() {
	Pressure();		//圧縮してファイルに保存する
	Sleep(1000);

	Expansion();	//ファイルから読み込んで展開する
	Sleep(1000);

	std::cout << std::endl << "全ての処理が完了しました" << std::endl<< "10秒後に終了します" << std::endl;
	Sleep(10000);
	return 0;
}

//圧縮
int Pressure() {
	int test[20] = { 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,0,0,0 };
	int test2[40] = { 9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };

	std::cout << "配列を定義しました" << std::endl;
	for (int i = 0; i < 20; i++)
		std::cout << test[i];
	std::cout << std::endl;
	for (int i = 0; i < 40; i++)
		std::cout << test2[i];
	std::cout << std::endl;

	Bytef *buffer = (Bytef*)malloc(64 * 1024 * 1024);		  //保存するデータより十分大きいメモリを確保
	int size = 0;

	//テストデータ1をメモリに書き込み
	memcpy(buffer + size, &test, sizeof(int) * 20);
	size += sizeof(int) * 20;

	//テストデータ2をメモリに書き込み
	memcpy(buffer + size, &test2, sizeof(int) * 40);
	size += sizeof(int) * 40;

	Bytef *press_buffer = (Bytef*)malloc(64 * 1024 * 1024);		//圧縮データより十分大きいメモリを確保
	uLong press_size;

	//~~~~~~~~~~~~~~~~~~~~~~~~~
	//	buffer のデータを圧縮して press_buffer に格納、圧縮後のデータサイズを press_size に格納する処理
	//~~~~~~~~~~~~~~~~~~~~~~~~~
	compress2(press_buffer, &press_size, buffer, uLong(sizeof(int) *  60), Z_BEST_COMPRESSION);				//圧縮
	std::cout << "データをメモリ上で圧縮しました" << std::endl;

	FILE *fp;
	errno_t err;
	err = fopen_s(&fp, "data.sav", "wb");				//書き込みでファイルを開く

	fwrite(&press_size, sizeof(uLong), 1, fp);			//圧縮データのサイズを書き出し

	fwrite(press_buffer, press_size, 1, fp);			//圧縮データを書き出し

	fclose(fp);											//ファイルを閉じる
	std::cout << "圧縮したデータをファイルに書き込みました" << std::endl;

	free(buffer);										//確保したメモリの解放
	free(press_buffer);

	return 0;
}

//展開
int Expansion() {
	//-------------------------------------------------------------------------------
	int r_test[20];
	int r_test2[40];
	std::cout << std::endl << "別の配列を定義しました" << std::endl;
	for (int i = 0; i < 20; i++)
		std::cout << r_test[i];
	std::cout << std::endl;
	for (int i = 0; i < 40; i++)
		std::cout << r_test2[i];
	std::cout << std::endl;
	//-------------------------------------------------------------------------------

	Bytef *buffer = (Bytef*)malloc(64 * 1024 * 1024);		  //保存するデータより十分大きいメモリを確保
	uLong size = sizeof(int) * 60;

	Bytef *press_buffer = (Bytef*)malloc(64 * 1024 * 1024);		//圧縮データより十分大きいメモリを確保
	uLong press_size;


	FILE *fp;
	errno_t err;
	err = fopen_s(&fp, "data.sav", "rb");		//読み込みでファイルを開く

	fread(&press_size, sizeof(uLong), 1, fp);		//圧縮データのサイズを読み込み

	fread(press_buffer, press_size, 1, fp);		//圧縮データを読み込み

	fclose(fp);									//ファイルを閉じる
	std::cout << "圧縮したデータをファイルから読み込みました" << std::endl;

	uncompress(buffer, &size, press_buffer, press_size);		//データを展開
	std::cout << "圧縮したデータをメモリ上で展開しました" << std::endl;

	size = 0;
	//テストデータ1をメモリから読み込む
	memcpy(r_test, buffer + size, sizeof(int) * 20);
	size += sizeof(int) * 20;

	//テストデータ2をメモリから読み込む
	memcpy(r_test2, buffer + size, sizeof(int) * 40);
	size += sizeof(int) * 40;

	free(buffer);										//確保したメモリの解放
	free(press_buffer);


	std::cout << "展開したデータを配列にコピーしました" << std::endl;
	for (int i = 0; i < 20; i++)
		std::cout << r_test[i];
	std::cout << std::endl;
	for (int i = 0; i < 40; i++)
		std::cout << r_test2[i];
	std::cout << std::endl;
	return 0;
}
最近は東方風アクションゲームを少しずつ作ってる人です
東方翠風燐FreeDownload⇒http://dxlib.o.oo7.jp/cgi/patio/read.cgi?no=212

返信

“C言語何でも質問掲示板” へ戻る