精华内容
下载资源
问答
  • 压缩与解压缩

    2018-07-14 16:29:57
    用C#实现对文件及文件夹的压缩与解压缩,有需要的可以拿走
  • 前端pako压缩与解压缩

    2020-12-22 15:09:26
    前端pako压缩与解压缩
  • 哈夫曼压缩与解压缩

    万次阅读 多人点赞 2018-08-13 12:52:01
    哈夫曼压缩与解压缩 目录 哈夫曼压缩与解压缩 一:引言 二:主要技术点 三:过程介绍 1、压缩: 2、解压缩 四:详细分析 一:准备过程 二:压缩 三:解压缩 五:结果演示 六:总结 七:源码地址 一:...

    哈夫曼压缩与解压缩

    目录

    哈夫曼压缩与解压缩

    一:引言

    二:主要技术点

    三:过程介绍

    1、压缩:

    2、解压缩

    四:详细分析

    一:准备过程

    二:压缩

    三:解压缩

    五:结果演示

    六:总结

    七:源码地址


    一:引言

    之前的两个贪吃蛇和巨大数的练习,总体来说难度不大,有好的算法和比较新颖的微译码补码。但是,哈夫曼压缩与解压缩可以说难度比前两个大得多,涉及的知识面更加广。做完这个,是对自己基本功的检测,更能提升自己的编程能力。 

    hffman编码的思想对文件进行压缩,主要原理是通过huffman编码来重新表示字符,使得出现频率高的字符编码短,出现少的字符编码长。整体下来的话,所需的总的bit位是减少的。但是要注意当大部分字符出现的频率都差不多时,huffman压缩的压缩效率会很低。

    编程环境:

    UE(或sublime),TDM-GCC。

    二:主要技术点

    1. 文件的各种操作
    2. 递归思想构造哈夫曼编码。
    3. 位运算思想进行压缩与解压缩。
    4. 自定义目标压缩文件头部元数据。
    5. 主函数带参,命令行参数。

    三:过程介绍

    1、压缩:

    1、统计字符种类及频度:ASCII码值当下标,字符频度当对应下标的值。

    2、构建哈夫曼树:在没有访问过的节点中,找最小字符频度下标来构建哈夫曼树。

    3、构建哈夫曼编码:递归思想构建。

    4、生成压缩文件(.ycyHuf后缀名):把字符的哈夫曼编码以二进制形式写入目标文件中。给压缩文件头部写入元数据,解压缩时需使用这些数据。

    注意事项:给目标文件写二进制数据时,最后一个字节如果不满八位,会产生垃圾数据,如果不进行处理,在解压后,就不能完整的还原。所以,需计算最后一个字节中的有效位数。

    2、解压缩

    1、根据压缩文件的头部元数据,得到字符种类和频度。

    2、构建哈夫曼树:在没有访问过的节点中,找最小字符频度下标来构建哈夫曼树。

    3、构建哈夫曼编码:递归思想构建。

    4、生成解压缩的文件(后缀名和源文件后缀名一样 )即可:一位一位的从压缩文件中读取信息,'1'向左子树走,'0'向右子树走。

    注意事项:压缩文件头部有元数据,所以,解压时需要把文件指针定位到真正的信息处。当碰到最后一字节的垃圾位时,应结束,否则解压出的信息和源文件会不匹配。

    四:详细分析

    一:准备过程

    三个关于位运算的宏

    1、取出index位,若取出的index位为0,则GET_BYTE值为假,否则为真

    #define GET_BYTE(vbyte, index) (((vbyte) & (1 << ((index) ^ 7))) != 0)

    2、把index位设置为‘1’

    #define SET_BYTE(vbyte, index) ((vbyte) |= (1 << ((index) ^ 7)))

    3、把index位设置为‘0’ 

    #define CLR_BYTE(vbyte, index) ((vbyte) &= (~(1 << ((index) ^ 7))))

    二:压缩

    1、统计字符种类和频度

    结构体定义:

    typedef struct ALPHA_FREQ {
    	unsigned char alpha;		//字符,考虑到文件中有汉字,所以定义成unsigned char
    	int freq;					//字符出现的频度
    } ALPHA_FREQ;

    代码分析:

    ALPHA_FREQ *getAlphaFreq(char *sourceFileName, int *alphaVariety) {
    	int freq[256] = {0};
    	int i;
    	int index;
    	ALPHA_FREQ *alphaFreq = NULL;
    	FILE *fpIn;
    	int ch;
    	
    	fpIn = fopen(sourceFileName, "rb");
    	
    	/*统计所有字符的频度*/
    	ch = fgetc(fpIn);
    	while(!feof(fpIn)) {
    		freq[ch]++;
    		ch = fgetc(fpIn);
    	}
    	fclose(fpIn);
    
    	/*统计所有字符的种类*/
    	for(i = 0; i < 256; i++) {
    		if(freq[i]) {
    			(*alphaVariety)++;
    		}
    	}
    
    	alphaFreq = (ALPHA_FREQ *) calloc(sizeof(ALPHA_FREQ), *alphaVariety);
    	for(i = index = 0; i < 256; i++) {
    		if(freq[i]) {
    			alphaFreq[index].alpha = i;
    			alphaFreq[index].freq = freq[i];
    			index++;
    		}
    	}
    
    	return alphaFreq;
    }

    统计字符及其频度,开始想到了一个笨办法。 如下:

    AlPHA_FREQ freq[256]
    count = 0;
    i = 0;
    
    while(str[i]) {
    	index = 0;
    	while(index < count) {
    		if(freq[index].alpha == str[i]) {
    			break;
    		}
    		index++
    	}
    	
    	if(index < count) {
    		freq[count].freq++;
    	} else {
    		freq[count].alpha = str[i];
    		freq[count].freq = 1;
    		count++;
    	}
    }

    但是,这样做有一个很大的缺点:随着字符串的增多,查找次数就会越来越多,极端情况下,没有重复的字符,那么就要执行n-1次,光一个统计字符的函数,其时间复杂度就达到了O(n^2);这显然是不合理的。因此,有一个更好的算法:构建一个大的数组,以字符的ASCII码值当下标,字符频度当对应下标的值,实现用空间,换时间的目的。例如'A'的频度,永远存放在下标为65的元素中。这样做,其时间复杂度达到了O(n)。

    2、初始化哈夫曼表

    结构体定义:

    typedef struct HUFFMAN_TAB {
    	ALPHA_FREQ alphaFreq;
    	int leftChild;
    	int rightChild;
    	boolean visited;
    	char *code;
    } HUFFMAN_TAB;
    HUFFMAN_TAB *initHuffmanTab(ALPHA_FREQ *alphaFreq, int alphaVariety, int *hufIndex) {
    	int i;
    	HUFFMAN_TAB *huffmanTab = NULL;
    
    	huffmanTab = (HUFFMAN_TAB *) calloc(sizeof(HUFFMAN_TAB), 2 * alphaVariety - 1);
    	//huffmanTab申请了 2 * alphaVariety - 1大小的空间,在这只用了 alphaVariety个,还剩alphaVariety - 1个
    	for(i = 0; i < alphaVariety; i++) {
    		hufIndex[alphaFreq[i].alpha] = i;	//把哈夫曼表中的字符和其对应的下标形成键值对,存到hufIndex中
    		huffmanTab[i].alphaFreq = alphaFreq[i];
    		huffmanTab[i].leftChild = huffmanTab[i].rightChild = -1;
    		huffmanTab[i].visited = FALSE;
    		huffmanTab[i].code = (char *) calloc(sizeof(char), alphaVariety);
    	}
    
    	return huffmanTab;
    }

    字符种类个数即为哈夫曼树的叶子结点个数,那么,根据完全二叉树的性质,这个哈夫曼树的总结点数为叶子节点数加度为2的节点数,所以,n总 = 2 * n0 - 1。先构建出哈夫曼表,为后面构建哈夫曼树做准备。注意,需设置一个visited成员来表示结点有没有被访问过。

    例如:字符串为“siytweusitweusitweusitwesitesitesitesieieieeeeee”,那么,统计出的结果为这样:

    根据这个哈夫曼表,可以画出哈夫曼树的结构了,如下:

    3、生成哈夫曼树

    生成哈夫曼树,我们需要把频度大的节点放在离根近的地方,频度小的节点放在离根远的地方。所以,需要进行最小字符频度的查找。

    int getMinFreq(HUFFMAN_TAB *huffmanTab, int count) {
    	int index;
    	int minIndex = NOT_INIT;
    
    	for(index = 0; index < count; index++) {
    		if(FALSE == huffmanTab[index].visited) {
    			if(NOT_INIT == minIndex || huffmanTab[index].alphaFreq.freq < huffmanTab[minIndex].alphaFreq.freq) {
    				minIndex = index;
    			}
    		}
    	}
    	huffmanTab[minIndex].visited = TRUE;
    
    	return minIndex;
    }
    void creatHuffmanTree(HUFFMAN_TAB *huffmanTab, int alphaVariety) {
    	int i;
    	int leftChild;
    	int rightChild;
    
    	//huffmanTab使用剩下的 alphaVariety - 1个空间
    	for(i = 0; i < alphaVariety - 1; i++) {
    		leftChild = getMinFreq(huffmanTab, alphaVariety + i);
    		rightChild = getMinFreq(huffmanTab, alphaVariety + i);
    		huffmanTab[alphaVariety + i].alphaFreq.alpha = '#';
    		huffmanTab[alphaVariety + i].alphaFreq.freq = huffmanTab[leftChild].alphaFreq.freq
    																									 + huffmanTab[rightChild].alphaFreq.freq;
    		huffmanTab[alphaVariety + i].leftChild = leftChild;
    		huffmanTab[alphaVariety + i].rightChild = rightChild;
    		huffmanTab[alphaVariety + i].visited = FALSE;
    	}
    }

    生成的哈夫曼树的表格形式如下

    4、生成哈夫曼编码

    哈夫曼树都已经生成,那么就需要生成哈夫曼编码了。

    思路:需要把哈夫曼树从根节点除法,进行遍历,向左子树为‘1’,右子树为‘0’;若碰到叶子结点,需要把编码存给对应的字符。若没有碰到叶子结点,则需要继续向下遍历。所以,这需要一个递归程序完成。

    void makeHuffmanCode(HUFFMAN_TAB *huffmanTab, int root, int index, char *code) {
    	if(huffmanTab[root].leftChild != -1 && huffmanTab[root].rightChild != -1) {
    		code[index] = '1';
    		makeHuffmanCode(huffmanTab, huffmanTab[root].leftChild, index + 1, code);
    		code[index] = '0';
    		makeHuffmanCode(huffmanTab, huffmanTab[root].rightChild, index + 1, code);
    	} else {
    		code[index] = 0;
    		strcpy(huffmanTab[root].code, code);
    	}
    }

    5、把哈夫曼编码以二进制位形式写入目标文件中

    此时,我们需要考虑一个问题。如果,光把“siytweusitweusitweusitwesitesitesitesieieieeeeee”这个字符串的哈夫曼编码以二进制形式写入目标文件,形成的目标文件中全是0101这种二进制代码,那如何解密呢?没有人能看懂这种二进制代码,所以,我们需要给目标文件的头部写入元数据(解释数据的数据),这些元数据主要包括源文件字符种类,字符频度。有了元数据,那么,就可以在解压缩程序中再构造一个完全相同的哈夫曼树,完成解压缩。

    所以,我们也可以构造我们的文件头部元数据,定义一个结构体如下:

    typedef struct HUF_FILE_HEAD {
    	unsigned char flag[3];				//压缩二进制文件头部标志 ycy
    	unsigned char alphaVariety;		//字符种类
    	unsigned char lastValidBit;		//最后一个字节的有效位数
    	unsigned char unused[11];			//待用空间
    } HUF_FILE_HEAD;								//这个结构体总共占用16个字节的空间

    依次给文件头部写入头部标志“ycy”, 字符种类alphaVariety, 最后一字节的有效位数lastValidBit。

    HUF_FILE_HEAD fileHead = {'y', 'c', 'y'};
    fileHead.alphaVariety = (unsigned char) alphaVariety;
    fileHead.lastValidBit = getlastValidBit(huffmanTab, alphaVariety);
    
    fwrite(&fileHead, sizeof(HUF_FILE_HEAD), 1, fpOut);
    fwrite(alphaFreq, sizeof(ALPHA_FREQ), alphaVariety, fpOut);

    lastValidBit计算过程:

    //取最后一个字节的有效位数
    int getlastValidBit(HUFFMAN_TAB *huffmanTab, int alphaVariety) {
    	int sum = 0;
    	int i;
    	
    	for(i = 0; i < alphaVariety; i++) {
    		sum += strlen(huffmanTab[i].code) * huffmanTab[i].alphaFreq.freq;
    		//如果不执行这一步,当数据长度超过int的表示范围,就会出错
    		sum &= 0xFF; //0xFF化为二进制位1111 1111,这样做sum始终是最后一个字节,8位
    	}
    	//举例:若最后生成7位二进制,划分为一个字节,那么,这一个字节只有7位为有效位,其余都是垃圾位。
    	//我们只需要取出这个字节的那7个有效位,所以sum和8取余即可
    	//sum = sum % 8 <=> sum = sum & 0x7
    	//返回最后一个字节的有效位数
    	sum &= 0x7;
    		
    	return sum == 0 ? 8 : sum;
    }

    完后,我们的.ycyHuf文件头部就写好了:

    头部元数据写好后,就需要写入真正的压缩信息了。但是,如何根据字符,迅速找到其哈夫曼编码呢?有一种笨办法,就是每次都根据当前字符,在哈夫曼表中查找,如果字符匹配,就找到了哈夫曼编码。

    for(i = 0; i < alphaVariety; i++) {
    	if(str[index] == huffmanTab[i]) {
    	hufCode = huffmanTab[i].code;
        }
    }

     但是,这样每次查找进行的比较次数平均为n / 2,若字符串长度为len,则时间复杂度为O(len * n / 2)。所以,这样做不是很好,有一种方法,可以不进行“查找”,就能“查找到”,时间复杂度为O(1); 这样,需要构造出一个“字符”:“下标”的键值对关系,字符可以直接定位,就完成了这个“迅速查找”的任务。所以,我在初始化哈夫曼表initHuffmanTab()函数中,构造了这个键值对关系。

    //构造键值对
    hufIndex[alphaFreq[i].alpha] = i;	//把哈夫曼表中的字符和其对应的下标形成键值对,存到hufIndex中
    //查找
    hufCode = huffmanTab[hufIndex[ch]].code;

    下来,就可以正式的给目标压缩文件中写数据了。

    ch = fgetc(fpIn);
    	while(!feof(fpIn)) {
    		hufCode = huffmanTab[hufIndex[ch]].code;
    		//把每个字符的哈夫曼编码一个一个过。
    		//如果是字符'0',就转换为二进制的0
    		//如果是字符'1',就转换为二进制的1
    		for(i = 0; hufCode[i]; i++) {
    			if('0' == hufCode[i]) {
    				//value为一个字节
    				//从第1位依次赋值,若大于八位(一个字节)了,就写入文件中
    				CLR_BYTE(value, bitIndex);
    			} else {
    				SET_BYTE(value, bitIndex);
    			}
    			bitIndex++;
    			if(bitIndex >= 8) {
    				bitIndex = 0;
    				fwrite(&value, sizeof(unsigned char), 1, fpOut);
    			}
    		}
    		ch = fgetc(fpIn);
    	}
    	//如果最后一次不满一个字节,依然需要写到文件中,注意:写入的最后一个字节可能会存在垃圾位
    	if(bitIndex) {
    		fwrite(&value, sizeof(unsigned char), 1, fpOut);
    	}

     如果遇到了字符‘0’,就利用位运算转换为二进制0,否则,为二进制1。 如果最后一次不满一个字节,依然需要写到文件中,注意:写入的最后一个字节可能会存在垃圾位。

    三:解压缩

    1、统计字符种类和频度

    直接从压缩的文件中的头部读取。先匹配是不是自定义的格式:

    fileHead = readFileHead(sourceFileName);
    if(!(fileHead.flag[0] == 'y' && fileHead.flag[1] == 'c' && fileHead.flag[2] == 'y')) {
    	printf("不可识别的文件格式\n");
    }

     如果是“ycy”,那么再统计字符种类和频度:

    ALPHA_FREQ *getAlphaFreq(char *sourceFileName, int *alphaVariety, HUF_FILE_HEAD fileHead) {
    	int freq[256] = {0};
    	int i;
    	int index;
    	ALPHA_FREQ *alphaFreq = NULL;
    	FILE *fpIn;
    	int ch;
    
    	*alphaVariety = fileHead.alphaVariety;
    	alphaFreq = (ALPHA_FREQ *) calloc(sizeof(ALPHA_FREQ), *alphaVariety);
    	fpIn = fopen(sourceFileName, "rb");
    	//略过前16个字节的元数据
    	fseek(fpIn, 16, SEEK_SET);
    	fread(alphaFreq, sizeof(ALPHA_FREQ), *alphaVariety, fpIn);
    	fclose(fpIn);
    
    	return alphaFreq;
    }

     2、初始化哈夫曼表

    和压缩过程一样。

    3、生成哈夫曼树

    和压缩过程一样。

    4、生成哈夫曼编码

    和压缩过程一样。

    5、从压缩文件中读取二进制信息,还原文件

     应该先利用fseek()函数把文件指针跳过前面的元数据和字符种类及频度,定位到真正需要还原的地方。一位一位的进行判断,'1'向左子树走,'0'向右子树走;若到达叶子结点,向文件中写入叶子结点下标对应的字符。再回到根结点继续;若超过一个字节,8位,则需要读取下一个字节。

    void huffmanDecoding(HUFFMAN_TAB *huffmanTab, char *sourceFileName, char *targetFileName, int alphaVariety, HUF_FILE_HEAD fileHead) {
    	int root = 2 * alphaVariety - 2;
    	FILE *fpIn;
    	FILE *fpOut;
    	boolean finished = FALSE;
    	unsigned char value;
    	unsigned char outValue;
    	int index = 0;
    	long fileSize;
    	long curLocation;
    
    	fpIn = fopen(sourceFileName, "rb");
    	fpOut = fopen(targetFileName, "wb");
    	fseek(fpIn, 0L, SEEK_END);
    	fileSize = ftell(fpIn);	//文件总长度fileSize
    	fseek(fpIn, 16 + 5 * fileHead.alphaVariety, SEEK_SET);	//略过前面16个字节的元数据,5字节的字符种类和频度
    	curLocation = ftell(fpIn);
    	
    	//从根出发,'1'向左子树走,'0'向右子树走,若到达叶子结点,输出叶子结点下标对应的字符。再回到根结点继续。
    	fread(&value, sizeof(unsigned char), 1, fpIn);
    	while(!finished) {
    		if(huffmanTab[root].leftChild == -1 && huffmanTab[root].rightChild == -1) {
    			outValue = huffmanTab[root].alphaFreq.alpha;
    			fwrite(&outValue, sizeof(unsigned char), 1, fpOut);
    			if(curLocation >= fileSize && index >= fileHead.lastValidBit) {
    				break;
    			} 
    			root = 2 * alphaVariety - 2;
    		}
    		
    		//取出的一个字节从第一位开始看,'1'向左子树走,'0'向右子树走
    		//若超过一个字节,8位,则需要读取下一个字节
    		if(GET_BYTE(value, index)) {
    			root = huffmanTab[root].leftChild;
    		} else {
    			root = huffmanTab[root].rightChild;
    		}
    		if(++index >= 8) {
    			index = 0;
    			fread(&value, sizeof(unsigned char), 1, fpIn);
    			curLocation = ftell(fpIn);
    		}
    	}
    
    	fclose(fpIn);
    	fclose(fpOut);
    }

    五:结果演示

    六:总结

    哈夫曼压缩与解压缩的项目完成了(以后还会继续完善,优化)。这个项目涉及了C语言里更加高级的操作(文件,位运算,主函数带参······)。哈夫曼压缩与解压缩涉及的知识是我目前以来接触的项目里最多,最广的,收获很多。经过这个练习,还是觉得写程序前,一定一定要认真,仔细的进行手工过程的分析,一定要分析的很到位,否则,程序的逻辑就会出错,酿成大错。最后,不要忘记free申请的空间,以免造成内存泄漏。

    七:源码地址

    https://github.com/yangchaoy259189888/Huffman-compress/

    纠错:
    感谢下面这位前辈指出的这两个问题,经过测试,确实,当初测试了一个bmp文件,成功压缩和解压缩之后,以为大功告成。其实,还有很多极端情况没有考虑到。比如:一个全是a的txt文件就会失败。

    本人能力有限,毕竟这个代码不是我一个人从头到尾完成的,其中的很多思想都来自教主。

    还请看到的大神和我沟通,争取把这个错误解决······

    展开全文
  • 关于ffmpeg的分析,对视频作压缩与解压缩处理 视频压缩与解压缩
  • 压缩与解压缩.rar

    2019-06-13 18:00:32
    压缩与解压缩代码,简单易懂,可直接调试使用,方便快捷
  • java实现压缩与解压缩

    2017-04-01 18:46:20
    java实现压缩与解压缩
  • 压缩与解压缩文件

    2014-06-10 16:03:41
    压缩与解压缩文件
  • 文件压缩与解压缩zip工具类
  • java实现压缩与解压缩源码
  • Python 压缩与解压缩20 Aug 2018python zipfilezip 文件是常用的压缩文件格式。 python zipfile模块提供了创建、读取、写入、追加等方法来进行zipfile文件操作。常用ZIP64扩展,最大支持4G。支持解密文档,但是当前...

    Python 压缩与解压缩

    20 Aug 2018

    python zipfile

    zip 文件是常用的压缩文件格式。 python zipfile模块提供了创建、读取、写入、追加等方法来进行zipfile文件操作。

    常用ZIP64扩展,最大支持4G。支持解密文档,但是当前不支持创建加密文档,解密速度比较慢。

    ZipFile类,读取、写入ZIP文件。

    PyZipFile类,创建ZIP归档,可以包含Python库

    ZipInfo类,查看归档文件的信息,常用函数getinfo()和infolist()

    常用函数:

    ZipFile(file, mode=’r’, compression=ZIP_STORED, allowZip64=True),创建压缩文件

    with ZipFile(‘spam.zip’, ‘w’) as myzip:

    myzip.write(‘eggs.txt’)

    is_zipfile(filename),是否是压缩文件

    ZipFile.open(name, mode=’r’, pwd=None, *, force_zip64=False),打开压缩文件

    with ZipFile(‘spam.zip’) as myzip:

    with myzip.open(‘eggs.txt’) as myfile:

    print(myfile.read())

    ZipFile.close(),关闭,必须有,也可以用with语句,省略此句

    ZipFile.extract(member, path=None, pwd=None),解压指定文件到当前目录,也可指定目录

    ZipFile.extractall(path=None, members=None, pwd=None),解压所有文件

    ZipFile.setpassword(pwd),设置密码

    ZipFile.write(filename, arcname=None, compress_type=None),写

    ZipFile.read(name, pwd=None),读

    压缩一个目录:

    def zip_dir(dirname, zipfilename):

    filelist = []

    if os.path.isfile(dirname):

    filelist.append(dirname)

    else :

    for root, dirs, files in os.walk(dirname):

    for dir in dirs:

    filelist.append(os.path.join(root,dir))

    for name in files:

    filelist.append(os.path.join(root, name))

    with zipfile.ZipFile(zipfilename, "w") as zf:

    for tar in filelist:

    arcname = tar[len(dirname):]

    print(tar + " -->rar: "+ arcname)

    zf.write(tar,arcname)

    解压的函数:

    def unzip_dir(zipfilename, unzipdirname):

    fullzipfilename = os.path.abspath(zipfilename)

    fullunzipdirname = os.path.abspath(unzipdirname)

    print("Start to unzip file %s to folder %s ..." % (zipfilename,unzipdirname))

    #Check input

    if not os.path.exists(fullzipfilename):

    print("Dir/File %s is not exist!" % fullzipfilename)

    return

    if not os.path.exists(fullunzipdirname):

    os.mkdir(fullunzipdirname)

    #Start extract files

    with zipfile.ZipFile(fullzipfilename,'r') as myzip:

    myzip.extractall(fullunzipdirname)

    print( "Unzip file succeed!")

    参考:

    展开全文
  • 赫夫曼压缩与解压缩

    2013-11-26 13:17:53
    C语言实现的Huffman压缩与解压缩编码。
  • lz4压缩与解压缩

    2019-09-26 08:59:24
    lz4压缩与解压缩库,已经编译过的,可以在VS上直接配置调用。vs2015测试通过。看说明
  • 压缩与解压缩软件

    2014-06-19 14:42:31
    压缩与解压缩软件,很常见并方便使用的一款小软件。
  • linux压缩与解压缩

    2020-01-16 09:46:12
    文章目录文档压缩与解压缩文档压缩文档解压缩 文档压缩与解压缩 tar命令用于压缩和解压缩文件 命令符 参数 tar(压缩/解压缩) -c 建立压缩文件-x 解压 -t 查看内容-r 向压缩归档文件末尾追加文件-u 更新原...

    文档压缩与解压缩

    tar命令用于压缩和解压缩文件

    命令符 参数
    tar(压缩/解压缩) -c 建立压缩文件
    -x 解压
    -t 查看内容
    -r 向压缩归档文件末尾追加文件
    -u 更新原压缩包中的文件
    这是5个独立的参数,压缩/解压只要用一个
    可以和下面的命令连用但只能用其中一个

    --------------------------
    -z 有gzip属性
    -j 有bz2属性
    -Z 有compress属性
    -v 显示所有过程
    -O 将文件解开到标准输出
    --------------------------
    -f 使用档案名字,是最后一个参数(这是必须的)

    文档压缩

    • 压缩为*.tar
      tar -cvf file_name.tar file_name
    • 压缩为*.tar.gz
      tar -zcvf file_name.tar.gz file_name
    • 压缩为*.tar.bz2
      tar -jcvf file_name.tar.bz2 file_name

    文档解压缩

    • 解压缩为*.tar
      tar -xvf file_name.tar
    • 解压缩为*.tar.gz
      tar -zxvf file_name.tar.gz
    • 解压缩为*.tar.bz2
      tar -jxvf file_name.tar.bz2
    展开全文
  • Java的压缩与解压缩ZIP压缩是一种通过特定的算法来减小计算机文件大小的机制。这种机制是一种很方便的`发明,尤其是对网络用户,因为它可以减小文件的字节总数,使文件能够通过较慢的互联网连接实现更快传输,此外还...

    Java的压缩与解压缩ZIP

    压缩是一种通过特定的算法来减小计算机文件大小的机制。这种机制是一种很方便的`发明,尤其是对网络用户,因为它可以减小文件的字节总数,使文件能够通过较慢的互联网连接实现更快传输,此外还可以减少文件的磁盘占用空间。下面小编准备了关于Java的压缩与解压缩ZIP,提供给大家参考!

    0c1ad841cdffac4d39c500d73ab85023.png

    压缩的

    import java.io.BufferedInputStream;

    import java.io.BufferedOutputStream;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

    import java.util.zip.ZipEntry;

    import java.util.zip.ZipOutputStream;

    public class Zip {

    static final int BUFFER = 2048;

    public static void main(String argv[]) {

    try {

    BufferedInputStream origin = null;

    FileOutputStream dest = new FileOutputStream("E:\\test\\myfiles.zip");

    ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(

    dest));

    byte data[] = new byte[BUFFER];

    File f = new File("e:\\test\\a\\");

    File files[] = f.listFiles();

    for (int i = 0; i < files.length; i++) {

    FileInputStream fi = new FileInputStream(files[i]);

    origin = new BufferedInputStream(fi, BUFFER);

    ZipEntry entry = new ZipEntry(files[i].getName());

    out.putNextEntry(entry);

    int count;

    while ((count = origin.read(data, 0, BUFFER)) != -1) {

    out.write(data, 0, count);

    }

    origin.close();

    }

    out.close();

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    解压缩的

    import java.io.BufferedInputStream;

    import java.io.BufferedOutputStream;

    import java.io.File;

    import java.io.FileOutputStream;

    import java.util.Enumeration;

    import java.util.zip.ZipEntry;

    import java.util.zip.ZipFile;

    public class UnZip {

    static final int BUFFER = 2048;

    public static void main(String argv[]) {

    try {

    String fileName = "E:\\test\\myfiles.zip";

    String filePath = "E:\\test\\";

    ZipFile zipFile = new ZipFile(fileName);

    Enumeration emu = zipFile.entries();

    int i=0;

    while(emu.hasMoreElements()){

    ZipEntry entry = (ZipEntry)emu.nextElement();

    //会把目录作为一个file读出一次,所以只建立目录就可以,之下的文件还会被迭代到。

    if (entry.isDirectory())

    {

    new File(filePath + entry.getName()).mkdirs();

    continue;

    }

    BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));

    File file = new File(filePath + entry.getName());

    //加入这个的原因是zipfile读取文件是随机读取的,这就造成可能先读取一个文件

    //而这个文件所在的目录还没有出现过,所以要建出目录来。

    File parent = file.getParentFile();

    if(parent != null && (!parent.exists())){

    parent.mkdirs();

    }

    FileOutputStream fos = new FileOutputStream(file);

    BufferedOutputStream bos = new BufferedOutputStream(fos,BUFFER);

    int count;

    byte data[] = new byte[BUFFER];

    while ((count = bis.read(data, 0, BUFFER)) != -1)

    {

    bos.write(data, 0, count);

    }

    bos.flush();

    bos.close();

    bis.close();

    }

    zipFile.close();

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    【Java的压缩与解压缩ZIP】相关文章:

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,490
精华内容 4,196
关键字:

压缩与解压缩