C

[C언어] 파일 압축/해제 프로그램 만들기

E58C 2023. 3. 29. 23:25

 

프로그램 설명

data.txt 라는 파일이 주어집니다.
이 파일을 압축해서 새로운 압축 파일을 생성합니다.
압축파일의 크기가 원래 파일보다 크기가 작다는 것을 보여줍니다.
압축파일을 해제하여 복구파일을 만들어냅니다.
이 복구 파일이 원본 파일과 동일하다는 것을 보여줍니다.

 

요구 사항

프로그램은 압축하는 것, 해제하는 것, 2개를 작성해야 합니다.
압축률: 기존 파일 크기 대비 80%보다는 작아야 합니다.
예를 들어, 기존 파일크기가 100이면, 압축파일 크기는 80보다 작아야 합니다.

 

data.txt
0.15MB

 

 

전체 코드

https://github.com/gayeonP/C-file-zip-unzip

 

GitHub - gayeonP/C-file-zip-unzip: c언어 파일 압축/해체 배치 프로그램

c언어 파일 압축/해체 배치 프로그램. Contribute to gayeonP/C-file-zip-unzip development by creating an account on GitHub.

github.com

 

 

 

코드 설명

main.c 에 전부 구현했습니다.

 

main 함수

int main(int argc, char* argv[]) {

	FILE* fp = NULL; // open
	FILE* fw = NULL; // write

	// 0 입력: 압축
	// 1 입력: 압축 해제
	int a = 0;
	printf("압축: 0\n압축해제: 1\n입력: ");
	int res = scanf("%d", &a);

	if (a) res = unzip(fp, fw);
	else res = zip(fp, fw);

	if (res == 0) printf("성공\n");
	else printf("실패\n");

	return 0;
}

먼저 파일 읽기와 쓰기를 해줄 FILE 포인터를 선언합니다.

배치 프로그램을 돋보이게 하기 위해 나름 GUI도 만들었습니다. 

 

초기 화면

0을 누르면 압축. 1을 누르면 압축 해제가 되도록 해줍니다. 0 -> 1 순서대로 입력해야 정상 작동입니다. 

물론 정상적으로 작동하지 않을 경우를 대비해 예외 처리를 해줍니다. zip과 unzip 함수의 return 값이 0이어야 정상적으로 작동된 것입니다. 그렇지 않을 경우에는 실패라고 판단합니다.

 

성공 경우
실패 경우

사용자가 0 또는 1이 아닌 수를 입력했을 때 예외처리는 완벽하지 않습니다. 그 경우는 없는걸로 가정했습니다.

다만 압축을 하지 않고 바로 해제를 할 경우는 실패라는 문구가 보이도록 했습니다.

 

 

 

zip 함수

int zip(FILE* fp, FILE* fw) {
	char str[MAX_SIZE + 1]; 

	if ((fp = fopen("data.txt", "rt")) == NULL) { // file open & error checking
		printf("unable to open file\n");
		return -1;
	}

	if ((fw = fopen("datazip.txt", "wt")) == NULL) { // file write & error checking
		printf("unable to write file\n");
		return -1;
	}

	int cnt = 0; // count var
	char ch = 0; // checking var
	while (fgets(str, sizeof(str), fp) != NULL) { 
		ch = str[0];
		for (unsigned int i = 0; i < strlen(str); i++) {
			if (ch == str[i]) {
				cnt++;

				// 파일의 끝이 마지막인것을 검사
				if ((strlen(str) != MAX_SIZE) && (i == strlen(str) - 1)) {
					fprintf(fw, "%c%d", ch, cnt);
					ch = str[i];
					cnt = 1;
				}
			}
			else {
				fprintf(fw, "%c%d", ch, cnt);
				ch = str[i];
				cnt = 1;
			}
		}
	}

	fclose(fp);
	fclose(fw);

	return 0;
}

먼저, 어떻게 압축을 할 것인가? 에 대한 답은 data.txt 파일을 보시면 알 수 있습니다. 

JJJJJJJJJJJJJJJJJJJJJJJJJJttttttt 

이런식으로 같은 알파벳이 반복되어 나타납니다. 그렇다면 J26t7 이런 형식으로 압축 파일을 만들어 줄 겁니다.

반복된 알파벳을 쓰고 그다음에 몇 번 반복되었는지 기록하는 식입니다.

 

1. 열고자 하는 파일이 있는지 검사

2. 파일을 쓸 수 있는지 검사

3. 10000개씩 datazip.txt 파일에 작성

3-1. 만일 파일의 끝이라면 while 문을 탈출해 적을 수 없음으로 파일에 쓰는 코드를 한 번 더 넣어줌

4. 스트림 닫기

5. 정상적으로 끝남을 알리는 0 리턴

 

 

 

unzip 함수 

int unzip(FILE* fp, FILE* fw) {
	if ((fp = fopen("datazip.txt", "rt")) == NULL) { // file open & error checking
		printf("unable to open file\n");
		return -1;
	}

	if ((fw = fopen("datanew.txt", "wt")) == NULL) { // file write & error checking
		printf("unable to write file\n");
		return -1;
	}

	char c = 0; // 알파벳을 담을 변수
	int d = 0; // count, 숫자를 담을 변수
	while (fscanf(fp, "%c%d", &c, &d) != EOF) {
		for (int i = 0; i < d; i++) {
			fputc(c, fw);
		}
	}

	fclose(fp);
	fclose(fw);

	return 0;
}

압축을 푸는 것은 쉽습니다. 알파벳과 숫자를 읽고 그 숫자만큼 알파벳을 반복적으로 쓰면 됩니다.

 

1. datazip 파일이 존재하는 검사

2. 파일을 쓸 수 있는지 검사

3. datazip 파일 끝까지 돌면서 파일 쓰기

4. 스트림 닫기

5. 정상적으로 끝남을 알리는 0 리턴

 

 

 

결과

data.txt (원본)

 

datazip.txt (압축 파일)

 

datanew.txt (압축해제 파일)

153KB -> 26KB 로 감소하였습니다. 원본 크기에 비해 16.9%로 감소했습니다. 

 

 

과제할 때 동영상도 찍었어야 했는데요.. 첨부합니다..

 

https://www.youtube.com/watch?v=5Zq5m7uRJi0 

 

 

학교 C언어프로그래밍 과제였습니다. 

안녕히계세요뿅