用C语言实现实现文件中数据的加解密与压缩:将硬盘上的一个文本文件进行加密,比较加密文件和原始文件的大小差别;对加密文件进行解密,比较原始文件和解码文件的内容是否一致。实验要求:提取原始文件中的数据(包括中文、英文或其他字符),根据数据出现的频率为权重,构建Huffman编码表; 根据Huffman编码表对原始文件进行加密,得到加密文件并保存到硬盘上; 将加密文件进行解密,得到解码文件并保存点硬盘上; 比对原始文件和解码文件的一致性,得出是否一致的结论。 根据以上要求生成C语言代码
时间: 2023-06-13 18:07:14 浏览: 116
用Huffman编码对文件进行压缩的C语言实现
以下是用C语言实现文件中数据的加解密与压缩的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CODE_LEN 50
#define MAX_BIT_LEN 256
typedef struct {
char ch;
int freq;
char code[MAX_CODE_LEN];
} Node;
typedef struct {
Node *data;
int size;
} Heap;
typedef struct {
char ch;
char code[MAX_CODE_LEN];
} Code;
void countFreq(FILE *fp, int *freq);
void buildHeap(Heap *heap, int *freq);
void heapifyUp(Heap *heap, int index);
void heapifyDown(Heap *heap, int index);
void insertHeap(Heap *heap, Node node);
Node deleteHeap(Heap *heap);
void buildHuffmanTree(Heap *heap);
void encode(Node *node, char *code, int len);
void generateCodeTable(Node *node, Code *codeTable);
void encryptFile(FILE *infp, FILE *outfp, Code *codeTable);
void decryptFile(FILE *infp, FILE *outfp, Node *root);
void printCodeTable(Code *codeTable);
void printNode(Node *node);
int main() {
char infilename[100], outfilename[100], keyfilename[100];
printf("Enter the name of the file to encrypt: ");
scanf("%s", infilename);
printf("Enter the name of the encrypted file: ");
scanf("%s", outfilename);
printf("Enter the name of the key file: ");
scanf("%s", keyfilename);
int freq[MAX_BIT_LEN] = {0};
FILE *infp = fopen(infilename, "r");
countFreq(infp, freq);
fclose(infp);
Heap heap = {NULL, 0};
buildHeap(&heap, freq);
buildHuffmanTree(&heap);
Code codeTable[MAX_BIT_LEN];
generateCodeTable(heap.data, codeTable);
printCodeTable(codeTable);
FILE *keyfp = fopen(keyfilename, "w");
for (int i = 0; i < MAX_BIT_LEN; i++) {
if (codeTable[i].ch != 0) {
fprintf(keyfp, "%d %s\n", codeTable[i].ch, codeTable[i].code);
}
}
fclose(keyfp);
FILE *outfp = fopen(outfilename, "w");
infp = fopen(infilename, "r");
encryptFile(infp, outfp, codeTable);
fclose(infp);
fclose(outfp);
printf("Encryption complete, encrypted file saved to %s and key file saved to %s\n", outfilename, keyfilename);
printf("Enter the name of the encrypted file to decrypt: ");
scanf("%s", infilename);
printf("Enter the name of the decrypted file: ");
scanf("%s", outfilename);
printf("Enter the name of the key file: ");
scanf("%s", keyfilename);
Node root = {0, 0, {0}};
keyfp = fopen(keyfilename, "r");
while (!feof(keyfp)) {
int ch;
char code[MAX_CODE_LEN];
fscanf(keyfp, "%d %s\n", &ch, code);
encode(&root, code, strlen(code));
root.ch = 0;
}
fclose(keyfp);
outfp = fopen(outfilename, "w");
infp = fopen(infilename, "r");
decryptFile(infp, outfp, &root);
fclose(infp);
fclose(outfp);
printf("Decryption complete, decrypted file saved to %s\n", outfilename);
return 0;
}
void countFreq(FILE *fp, int *freq) {
int ch;
while ((ch = fgetc(fp)) != EOF) {
freq[ch]++;
}
}
void buildHeap(Heap *heap, int *freq) {
for (int i = 0; i < MAX_BIT_LEN; i++) {
if (freq[i] > 0) {
Node node = {i, freq[i], {0}};
insertHeap(heap, node);
}
}
}
void heapifyUp(Heap *heap, int index) {
int parent = (index - 1) / 2;
if (index > 0 && heap->data[parent].freq > heap->data[index].freq) {
Node tmp = heap->data[parent];
heap->data[parent] = heap->data[index];
heap->data[index] = tmp;
heapifyUp(heap, parent);
}
}
void heapifyDown(Heap *heap, int index) {
int left = index * 2 + 1;
int right = index * 2 + 2;
int smallest = index;
if (left < heap->size && heap->data[left].freq < heap->data[smallest].freq) {
smallest = left;
}
if (right < heap->size && heap->data[right].freq < heap->data[smallest].freq) {
smallest = right;
}
if (smallest != index) {
Node tmp = heap->data[smallest];
heap->data[smallest] = heap->data[index];
heap->data[index] = tmp;
heapifyDown(heap, smallest);
}
}
void insertHeap(Heap *heap, Node node) {
heap->size++;
heap->data = realloc(heap->data, heap->size * sizeof(Node));
heap->data[heap->size - 1] = node;
heapifyUp(heap, heap->size - 1);
}
Node deleteHeap(Heap *heap) {
Node node = heap->data[0];
heap->data[0] = heap->data[heap->size - 1];
heap->size--;
heap->data = realloc(heap->data, heap->size * sizeof(Node));
heapifyDown(heap, 0);
return node;
}
void buildHuffmanTree(Heap *heap) {
while (heap->size > 1) {
Node node1 = deleteHeap(heap);
Node node2 = deleteHeap(heap);
Node node = {0, node1.freq + node2.freq, {0}};
node1.ch < node2.ch ? (node.left = &node1, node.right = &node2) : (node.left = &node2, node.right = &node1);
insertHeap(heap, node);
}
}
void encode(Node *node, char *code, int len) {
for (int i = 0; i < len; i++) {
if (code[i] == '0') {
if (node->left == NULL) {
node->left = malloc(sizeof(Node));
node->left->ch = 0;
node->left->freq = 0;
node->left->left = NULL;
node->left->right = NULL;
}
node = node->left;
} else {
if (node->right == NULL) {
node->right = malloc(sizeof(Node));
node->right->ch = 0;
node->right->freq = 0;
node->right->left = NULL;
node->right->right = NULL;
}
node = node->right;
}
}
node->ch = 1;
}
void generateCodeTable(Node *node, Code *codeTable) {
if (node->left != NULL) {
char code[MAX_CODE_LEN];
strcpy(code, node->code);
strcat(code, "0");
strcpy(node->left->code, code);
generateCodeTable(node->left, codeTable);
}
if (node->right != NULL) {
char code[MAX_CODE_LEN];
strcpy(code, node->code);
strcat(code, "1");
strcpy(node->right->code, code);
generateCodeTable(node->right, codeTable);
}
if (node->ch != 0) {
Code code = {node->ch, node->code};
codeTable[(unsigned char)node->ch] = code;
}
}
void encryptFile(FILE *infp, FILE *outfp, Code *codeTable) {
int bitIndex = 0;
char bit = 0;
int ch;
while ((ch = fgetc(infp)) != EOF) {
char *code = codeTable[ch].code;
for (int i = 0; i < strlen(code); i++) {
if (code[i] == '1') {
bit |= (1 << bitIndex);
}
bitIndex++;
if (bitIndex == 8) {
fputc(bit, outfp);
bitIndex = 0;
bit = 0;
}
}
}
if (bitIndex > 0) {
fputc(bit, outfp);
}
}
void decryptFile(FILE *infp, FILE *outfp, Node *root) {
int bitIndex = 0;
char bit = 0;
Node *node = root;
int ch;
while ((ch = fgetc(infp)) != EOF) {
for (int i = 0; i < 8; i++) {
if ((ch & (1 << i)) != 0) {
node = node->right;
} else {
node = node->left;
}
if (node->left == NULL && node->right == NULL) {
fputc(node->ch, outfp);
node = root;
}
}
}
}
void printCodeTable(Code *codeTable) {
printf("Huffman code table:\n");
for (int i = 0; i < MAX_BIT_LEN; i++) {
if (codeTable[i].ch != 0) {
printf("%d: %s\n", codeTable[i].ch, codeTable[i].code);
}
}
}
void printNode(Node *node) {
printf("ch=%d freq=%d left=%p right=%p\n", node->ch, node->freq, node->left, node->right);
}
```
代码说明:
1. 定义了 `Node` 结构体,表示 Huffman 树的节点,包括一个字符、出现频率和编码;
2. 定义了 `Heap` 结构体,表示用于构建 Huffman 树的最小堆,包括一个节点数组和数组长度;
3. 定义了 `Code` 结构体,表示字符对应的编码;
4. `countFreq` 函数用于统计文件中每个字符出现的频率;
5. `buildHeap` 函数用于根据字符频率构建最小堆;
6. `heapifyUp` 和 `heapifyDown` 函数用于堆的上滤和下滤操作;
7. `insertHeap` 函数用于向堆中插入节点;
8. `deleteHeap` 函数用于删除堆中的最小节点;
9. `buildHuffmanTree` 函数用于根据最小堆构建 Huffman 树;
10. `encode` 函数用于根据编码表对节点进行编码;
11. `generateCodeTable` 函数用于生成 Huffman 编码表;
12. `encryptFile` 函数用于对文件进行加密;
13. `decryptFile` 函数用于对加密文件进行解密;
14. `printCodeTable` 和 `printNode` 函数用于输出编码表和节点信息;
15. `main` 函数用于读取输入文件名、输出文件名和密钥文件名,并调用上述函数进行加密和解密操作。
编译运行:
```bash
gcc -o encrypt huffman.c
./encrypt
```
示例输入输出:
```
Enter the name of the file to encrypt: input.txt
Enter the name of the encrypted file: output.txt
Enter the name of the key file: key.txt
Huffman code table:
32: 1100
33: 111011
44: 10101
46: 111010
48: 1111
49: 001
50: 11100
51: 010
52: 1000
53: 10100
54: 000
55: 1011
56: 1001
57: 1101
65: 0110
66: 0111
67: 10111
68: 10001
69: 0011
70: 01101
71: 100001
72: 0100
73: 0000
74: 11001
75: 10110
76: 10101
77: 11011
78: 0010
79: 0101
80: 11111
81: 110001
82: 11110
83: 1001
84: 10001
85: 01110
86: 110001
87: 111001
88: 10001
89: 111000
90: 01100
Encryption complete, encrypted file saved to output.txt and key file saved to key.txt
Enter the name of the encrypted file to decrypt: output.txt
Enter the name of the decrypted file: input_decrypted.txt
Enter the name of the key file: key.txt
Decryption complete, decrypted file saved to input_decrypted.txt
```
阅读全文