C语言中的文件压缩和解压缩技术是什么?

文件压缩和解压缩是计算机领域中常用的技术,通过压缩可以减小文件的体积,从而更高效地存储和传输数据。在C语言中,有多种文件压缩和解压缩的技术和算法可供选择。本文将介绍一些常见的压缩和解压缩技术,以及在C语言中如何实现它们。

1. 文件压缩的原理

文件压缩的基本原理是通过一定的算法和技术,将文件中的冗余信息去除或者用更紧凑的方式表示,从而减小文件的大小。压缩算法可以分为两大类:

1.1 无损压缩

无损压缩是指通过压缩算法压缩文件,然后再解压缩还原为原始文件时,不会损失任何信息。常见的无损压缩算法有:

  • Run-Length Encoding (RLE):基于相同连续数据的重复次数进行编码。例如,"AAAABBBCCDAA" 可以表示为 "4A3B2C1D2A"。

  • Huffman编码:根据字符出现的频率来构建可变长度的编码,使得频率高的字符用较短的编码表示,频率低的字符用较长的编码表示。

  • Lempel-Ziv算法系列:包括LZ77、LZ78和LZW等,通过字典压缩方法,将文件中的重复序列用较短的标记表示。

1.2 有损压缩

有损压缩是指在压缩文件时,可能会损失一些信息,但在实际应用中,损失的信息对整体的影响不大。常见的有损压缩算法有:

  • JPEG(Joint Photographic Experts Group):主要用于压缩图像文件,采用离散余弦变换(DCT)进行频域压缩。

  • MP3(MPEG-1 Audio Layer III):用于压缩音频文件,采用梅尔频率倒谱系数(MFCC)等方法进行频域压缩。

  • 视频压缩算法:包括H.264、HEVC等,主要用于压缩视频文件,采用运动估计、变换编码等技术。

2. C语言中的文件压缩

在C语言中,实现文件压缩通常需要借助相关的库或者手动实现压缩算法。下面以Huffman编码为例,演示在C语言中如何实现文件压缩。

2.1 Huffman编码压缩

Huffman编码的基本步骤包括构建哈夫曼树和生成编码表。以下是一个简单的C语言程序,用于对文件进行Huffman编码压缩:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_TREE_NODES 256// 哈夫曼树节点
struct HuffmanNode {char data;int frequency;struct HuffmanNode *left, *right;
};// 优先队列节点
struct PriorityQueueNode {struct HuffmanNode *data;struct PriorityQueueNode *next;
};// 优先队列
struct PriorityQueue {struct PriorityQueueNode *front;
};// 创建哈夫曼树节点
struct HuffmanNode* createHuffmanNode(char data, int frequency) {struct HuffmanNode* node = (struct HuffmanNode*)malloc(sizeof(struct HuffmanNode));node->data = data;node->frequency = frequency;node->left = node->right = NULL;return node;
}// 创建优先队列节点
struct PriorityQueueNode* createPriorityQueueNode(struct HuffmanNode* data) {struct PriorityQueueNode* node = (struct PriorityQueueNode*)malloc(sizeof(struct PriorityQueueNode));node->data = data;node->next = NULL;return node;
}// 创建空的优先队列
struct PriorityQueue* createPriorityQueue() {struct PriorityQueue* queue = (struct PriorityQueue*)malloc(sizeof(struct PriorityQueue));queue->front = NULL;return queue;
}// 插入节点到优先队列
void insert(struct PriorityQueue* queue, struct HuffmanNode* data) {struct PriorityQueueNode* newNode = createPriorityQueueNode(data);if (queue->front == NULL || data->frequency < queue->front->data->frequency) {newNode->next = queue->front;queue->front = newNode;} else {struct PriorityQueueNode* temp = queue->front;while (temp->next != NULL && temp->next->data->frequency < data->frequency) {temp = temp->next;}newNode->next = temp->next;temp->next = newNode;}
}// 构建哈夫曼树
struct HuffmanNode* buildHuffmanTree(char data[], int frequency[], int size) {struct PriorityQueue* queue = createPriorityQueue();for (int i = 0; i < size; i++) {insert(queue, createHuffmanNode(data[i], frequency[i]));}while (queue->front->next != NULL) {struct HuffmanNode* left = queue->front->data;dequeue(queue);struct HuffmanNode* right = queue->front->data;dequeue(queue);struct HuffmanNode* merged = createHuffmanNode('$', left->frequency + right->frequency);merged->left = left;merged->right = right;insert(queue, merged);}struct HuffmanNode* root = queue->front->data;dequeue(queue);free(queue);return root;
}// 生成Huffman编码表
void generateHuffmanCodes(struct HuffmanNode* root, int arr[], int top, int codeTable[][MAX_TREE_NODES]) {if (root->left) {arr[top] = 0;generateHuffmanCodes(root->left, arr, top + 1, codeTable);}if (root->right) {arr[top] = 1;generateHuffmanCodes(root->right, arr, top + 1, codeTable);}if (!root->left && !root->right) {for (int i = 0; i < top; i++) {codeTable[root->data][i] = arr[i];}codeTable[root->data][top] = -1; // 结束标记}
}// 从优先队列中出队一个节点
void dequeue(struct PriorityQueue* queue) {if (queue->front == NULL) {return;}struct PriorityQueueNode* temp = queue->front;queue->front = queue->front->next;free(temp);
}// 压缩文件
void compressFile(char inputFile[], char outputFile[]) {FILE *input, *output;input = fopen(inputFile, "rb");output = fopen(outputFile, "wb");if (input == NULL || output == NULL) {printf("File open error\n");return;}char data[MAX_TREE_NODES];int frequency[MAX_TREE_NODES] = {0};// 统计字符频率int ch;while ((ch = fgetc(input)) != EOF) {data[ch]++;frequency[ch]++;}struct HuffmanNode* root = buildHuffmanTree(data, frequency, MAX_TREE_NODES);int arr[MAX_TREE_NODES];int codeTable[MAX_TREE_NODES][MAX_TREE_NODES];generateHuffmanCodes(root, arr, 0, codeTable);// 写入压缩后的数据fseek(input, 0, SEEK_SET);while ((ch = fgetc(input)) != EOF) {int i = 0;while (codeTable[ch][i] != -1) {fprintf(output, "%d", codeTable[ch][i]);i++;}}fclose(input);fclose(output);
}int main() {compressFile("input.txt", "compressed.bin");return 0;
}

上述程序中,首先统计输入文件中每个字符的频率,然后构建Huffman树,生成Huffman编码表,最后使用编码表将输入文件中的数据进行压缩,并将结果写入输出文件。

2.2 文件解压缩

文件解压缩的过程与压缩相反,需要根据压缩时生成的编码表将压缩文件还原为原始文件。以下是一个简单的C语言程序,用于对Huffman编码压缩后的文件进行解压缩:

#include <stdio.h>#define MAX_TREE_NODES 256// 哈夫曼树节点
struct HuffmanNode {char data;struct HuffmanNode *left, *right;
};// 从优先队列中出队一个节点
void dequeue(struct PriorityQueue* queue);// 优先队列节点
struct PriorityQueueNode {struct HuffmanNode *data;struct PriorityQueueNode *next;
};// 优先队列
struct PriorityQueue {struct PriorityQueueNode *front;
};// 创建哈夫曼树节点
struct HuffmanNode* createHuffmanNode(char data) {struct HuffmanNode* node = (struct HuffmanNode*)malloc(sizeof(struct HuffmanNode));node->data = data;node->left = node->right = NULL;return node;
}// 创建优先队列节点
struct PriorityQueueNode* createPriorityQueueNode(struct HuffmanNode* data) {struct PriorityQueueNode* node = (struct PriorityQueueNode*)malloc(sizeof(struct PriorityQueueNode));node->data = data;node->next = NULL;return node;
}// 创建空的优先队列
struct PriorityQueue* createPriorityQueue() {struct PriorityQueue* queue = (struct PriorityQueue*)malloc(sizeof(struct PriorityQueue));queue->front = NULL;return queue;
}// 插入节点到优先队列
void insert(struct PriorityQueue* queue, struct HuffmanNode* data) {struct PriorityQueueNode* newNode = createPriorityQueueNode(data);if (queue->front == NULL) {newNode->next = queue->front;queue->front = newNode;} else {struct PriorityQueueNode* temp = queue->front;while (temp->next != NULL) {temp = temp->next;}temp->next = newNode;}
}// 从优先队列中出队一个节点
void dequeue(struct PriorityQueue* queue) {if (queue->front == NULL) {return;}struct PriorityQueueNode* temp = queue->front;queue->front = queue->front->next;free(temp);
}// 构建哈夫曼树
struct HuffmanNode* buildHuffmanTreeFromFile(FILE* input) {int ch;struct PriorityQueue* queue = createPriorityQueue();while ((ch = fgetc(input)) != EOF) {struct HuffmanNode* node = createHuffmanNode(ch);insert(queue, node);}while (queue->front->next != NULL) {struct HuffmanNode* left = queue->front->data;dequeue(queue);struct HuffmanNode* right = queue->front->data;dequeue(queue);struct HuffmanNode* merged = createHuffmanNode('$');merged->left = left;merged->right = right;insert(queue, merged);}struct HuffmanNode* root = queue->front->data;dequeue(queue);free(queue);return root;
}// 解压缩文件
void decompressFile(char inputFile[], char outputFile[]) {FILE *input, *output;input = fopen(inputFile, "rb");output = fopen(outputFile, "w");if (input == NULL || output == NULL) {printf("File open error\n");return;}struct HuffmanNode* root = buildHuffmanTreeFromFile(input);struct HuffmanNode* current = root;int bit;while ((bit = fgetc(input)) != EOF) {if (bit == '0') {current = current->left;} else if (bit == '1') {current = current->right;}if (current->left == NULL && current->right == NULL) {fprintf(output, "%c", current->data);current = root;}}fclose(input);fclose(output);
}int main() {decompressFile("compressed.bin", "output.txt");return 0;
}

在这个解压缩程序中,首先从压缩文件中读取位('0'或'1'),根据Huffman树的结构逐步还原原始文件中的字符,并将结果写入输出文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/226126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【正点原子STM32连载】 第十五章 窗口看门狗实验 摘自【正点原子】APM32E103最小系统板使用指南

1&#xff09;实验平台&#xff1a;正点原子APM32E103最小系统板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第十…

代码随想录——链表 刷题记录

链表数据结构 public class ListNode {int val;ListNode next;// 构造函数public ListNode() {}public ListNode(int val) {this.val val;}public ListNode(int val, ListNode next) {this.val val;this.next next;} }203.移除链表元素 707.设计链表 单链表双链表 publi…

软件测试小课堂

1.测试用例的作用 一、理清测试思路 实际结果、预期结果、目的、bug二、评估工作进度 每个测试用例覆盖多少个功能点&#xff0c;有多少没有覆盖三、提前准备测试数据 正向数据、反向数据、等价类、边界值四、评估工作量五、进行回归测试六、企业角度 人员流动不影响测试进度&…

遥感图像分割系统:融合空间金字塔池化(FocalModulation)改进YOLOv8

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 遥感图像分割是遥感技术领域中的一个重要研究方向&#xff0c;它的目标是将遥感图像中的不同地物或地物类别进行有效的分割和识别。随着遥感技术的不断发展和遥感…

Hystrix使用及原理概述

一、背景 1. 当前问题 一个系统&#xff0c;所有请求共用同一个APP容器&#xff08;Tomcat/jetty/等&#xff09;&#xff0c;共用一个用户线程池&#xff0c;依赖多个不同的远程服务。 当系统健康时&#xff0c;处理请求的延时较低&#xff0c;服务正常运行&#xff1b;当某…

大模型下开源文档解析工具总结及技术思考

1 基于文档解析工具的方法 pdf解析工具 导图一览&#xff1a; PyPDF2提取txt&#xff1a; import PyPDF2 def extract_text_from_pdf(pdf_path):with open(pdf_path, rb) as file:pdf_reader PyPDF2.PdfFileReader(file)num_pages pdf_reader.numPagestext ""f…

漏洞复现-网神SecGate3600防火墙敏感信息泄露漏洞(附漏洞检测脚本)

免责声明 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…

记录 | ubuntu安装Albert

ubuntu 安装 Albert # 依赖安装 sudo apt install cmake pybind11-dev libmuparser-dev libqalculate-dev libxcb-cursor0 libgl1-mesa-dev# 安装Qt6git clone --recursive https://github.com/albertlauncher/albert.gitcd albert # 若 albert/plugin clone失败&#xff0c;则…

算法leetcode|92. 反转链表 II(rust重拳出击)

文章目录 92. 反转链表 II&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a;进阶&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 92. 反转链表 II&#xff1a; 给你单链表的…

迈入数据结构殿堂——时间复杂度和空间复杂度

目录 一&#xff0c;算法效率 1.如何衡量一个算法的好坏&#xff1f; 2.算法效率 二&#xff0c;时间复杂度 1.时间复杂度的概念 2.大O的渐进表示法 3.推导大O的渐进表示法 4.常见时间复杂度举例 三&#xff0c;空间复杂度 一&#xff0c;算法效率 数据结构和算法是密…

关于成品项目分辨率适配解决方案

最近接手一个项目,开发马上完成,客户突然提出产品的分辨率适配不太友好; ......领导一声令下,改吧 怎么改?量太大,项目用的reactantdvumi,react页面没有800个也有500个了,一个一个页面改,不太现实,耗时太久,决定找新的其他方案. 在网上找了一些文章,决定用css3 transfrom …

迅腾文化品牌网络推广助力企业:保持品牌稳定,发展更多消费者信任,提升品牌忠诚度

迅腾文化品牌网络推广助力企业&#xff1a;保持品牌稳定&#xff0c;发展更多消费者信任&#xff0c;提升品牌忠诚度 在当今快速发展的互联网时代&#xff0c;品牌网络推广已经成为企业发展的重要手段。迅腾文化作为专业的品牌网络推广公司&#xff0c;致力于帮助企业实现品牌…

单机版ElasticSearch健康状态yellow解决---ElasticSearch工作笔记035

ElasticSearch启动的时候报错: [2023-12-12T14:53:01,356][WARN ][r.suppressed ] [node-1] path: /.kibana/_doc/space%3Adefault, params: {index=.kibana, id=space:default} org.elasticsearch.action.NoShardAvailableActionException: No shard available f…

产品经理之如何编写需求PRD文档(医疗HIS项目详细案例模板)

目录 前言 一.需求文档的含义 二.需求文档的作用及目的 三.编写前的准备 四.需求大纲 五.案例模板 前言 继上两篇的可行性分析文档和竞品分析报告&#xff0c;本篇将继续介绍如何编写PRD文档&#xff0c;并且会附上以医疗项目为例的模板 一.需求文档的含义 需求文…

【C语言(十五)】

动态内存管理 一、为什么要有动态内存分配? 我们已经掌握的内存开辟方式有&#xff1a; int val 20 ; // 在栈空间上开辟四个字节 char arr[ 10 ] { 0 }; // 在栈空间上开辟 10 个字节的连续空间 但是上述的开辟空间的方式有两个特点&#xff1a; • 空间开辟大小是固…

camera卷帘快门(Rolling Shutter)与全局快门(Global Shutter)

首先来看一下什么叫快门&#xff1a; 快门是照相机用来控制感光元件有效曝光时间的装置。可以理解为光线要想打到相机传感器上必经的一道门。如果快门关着&#xff0c;那么光线进不去&#xff0c;感光元件就无法曝光&#xff1b;门开了&#xff0c;光线进来了&#xff0c;感光元…

FlinkSQL中的窗口

多维分析 需求&#xff1a;有一张test表&#xff0c;表的字段为&#xff1a;A, B, C, amount, 其中A, B, C为维度字段&#xff0c;求以三个维度任意组合&#xff0c;统计sum(amount) Union方案&#xff1a; A, B, C的任意组合共有8种&#xff0c;分别为&#xff08;A, B,C,AB…

C语言:指针与数组易错辨析

前言&#xff1a; 在学校学习指针和数组的联系时&#xff0c;对指针与数组的结合产生了很大的疑惑&#xff0c;后来不断查找资料&#xff0c;本人对指针与数组的综合有了一定的理解&#xff0c;现进行综合讨论辨析 数组指针&#xff1a; 数组指针&#xff0c;即为指向数组类…

OpenAI 认为超人工智能即将来临,并希望构建工具来控制它

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

机器学习中数据的特征表示

在实际应用中&#xff0c;数据的类型多种多样&#xff0c;比如文本、音频、图像、视频等。不同类型的数据&#xff0c;其原始特征的空间也不相同。比如一张灰度图像&#xff08;像素数量为 &#x1d437;&#xff09;的特征空间为 [0, 255]&#x1d437;&#xff0c;一个自然语…