-
2019-07-26 14:54:09
Java实现文件压缩与解压缩-----zip
Java中实现zip的压缩与解压缩
1 基本概念
- ZipOutputStream 实现文件的压缩
- ZipOutputStream (OutputStream out) 创建新的zip输出流
- void putNextEntry(ZipEntry e) 开始写入新的zip文件条目并将流定位到条目数据的开始处
条目指的是一个文件夹下的多个文件。 - ZipEntry(String name) 使用指定名称创建新的zip条目
- ZipIutputStream实现文件的解压
- ZipIutputStream (IutputStream out) 创建新的zip输入流
- ZipEntry getNextEntry()读取下一个zip条目并将流定位到该条目数据的开始处
2 zip压缩
2.1 zip压缩代码实现
- 程序完整代码
import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class Uzip { /** * 压缩 */ public static void zip(String input, String output, String name) throws Exception { //要生成的压缩文件 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(output)); String[] paths = input.split("\\|"); File[] files = new File[paths.length]; byte[] buffer = new byte[1024]; for (int i = 0; i < paths.length; i++) { files[i] = new File(paths[i]); } for (int i = 0; i < files.length; i++) { FileInputStream fis = new FileInputStream(files[i]); if (files.length == 1 && name != null) { out.putNextEntry(new ZipEntry(name)); } else { out.putNextEntry(new ZipEntry(files[i].getName())); } int len; // 读入需要下载的文件的内容,打包到zip文件 while ((len = fis.read(buffer)) > 0) { out.write(buffer, 0, len); } out.closeEntry(); fis.close(); } out.close(); } public static void main(String[ ] args){ try { zip("E:\\Testzip\\test\\ytt.html","E:\\Test.zip","testytt"); } catch (Exception e) { e.printStackTrace(); } } }
maven依赖:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-compress</artifactId> <version>1.12</version> </dependency>
- 运行程序:
3.程序解读:
- ZipEntry(String name) 只能实现一个固定条目的压缩,也就是你压缩什么就得写仔细它的路径,多个子文件压缩写法如下:
public static void main(String[ ] args){ try { zip("E:\\Testzip\\test\\ytt.html|E:\\Testzip\\uugg.html","E:\\Test.zip",null); } catch (Exception e) { e.printStackTrace(); } } }
注意:
一定要写全
E:\\Testzip\\test\\ytt.html
,如果写E:\\Testzip\\test\\ytt
会报错,报错信息无访问权限。String input :定义的是待压缩文件的条目。
String output:定义得到的压缩文件包.zip的名字。
String name:定义压缩后的条目的名字,如果与压缩前保持一致,定义name为null即可。
此程序无法实现对空文件夹的压缩。
2.2 zip压缩代码改进
改进的代码可以实现对任意文件的压缩,注意要写全文件类型,比如ytt.html,不允许省略.html。
import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * date: 2019/07/26 * writed by yangtingting */ public class FileZip { /** * zip文件压缩 * @param inputFile 待压缩文件夹/文件名 * @param outputFile 生成的压缩包名字 */ public static void ZipCompress(String inputFile, String outputFile) throws Exception { //创建zip输出流 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputFile)); //创建缓冲输出流 BufferedOutputStream bos = new BufferedOutputStream(out); File input = new File(inputFile); compress(out, bos, input,null); bos.close(); out.close(); } /** * @param name 压缩文件名,可以写为null保持默认 */ //递归压缩 public static void compress(ZipOutputStream out, BufferedOutputStream bos, File input, String name) throws IOException { if (name == null) { name = input.getName(); } //如果路径为目录(文件夹) if (input.isDirectory()) { //取出文件夹中的文件(或子文件夹) File[] flist = input.listFiles(); if (flist.length == 0)//如果文件夹为空,则只需在目的地zip文件中写入一个目录进入 { out.putNextEntry(new ZipEntry(name + "/")); } else//如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩 { for (int i = 0; i < flist.length; i++) { compress(out, bos, flist[i], name + "/" + flist[i].getName()); } } } else//如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入zip文件中 { out.putNextEntry(new ZipEntry(name)); FileInputStream fos = new FileInputStream(input); BufferedInputStream bis = new BufferedInputStream(fos); int len; //将源文件写入到zip文件中 byte[] buf = new byte[1024]; while ((len = bis.read(buf)) != -1) { bos.write(buf,0,len); } bis.close(); fos.close(); } } public static void main(String[] args) { try { ZipCompress("D:\\Test", "D:\\TestbyYTT.zip"); } catch (Exception e) { e.printStackTrace(); } } }
3 zip解压
3.1 zip不完美实现
- 这个网上有很多代码的,比如:
package file; import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; public class Decompressing { public static void main(String[] args) { File file = new File("E:\\hello.zip");//当前压缩文件 ZipInputStream zin;//创建ZipInputStream对象 try { ZipFile zipFile = new ZipFile(file);//创建压缩文件对象 zin = new ZipInputStream(new FileInputStream(file));//实例化对象,指明要解压的文件 ZipEntry entry ; while (((entry=zin.getNextEntry())!=null)&& !entry.isDirectory()){//如果entry不为空,并不在同一个目录下 File tmp = new File(entry.getName());//解压出的文件路径 if (!tmp.exists()){//如果文件不存在 tmp.getParentFile().mkdirs();//创建文件父类文件夹路径 OutputStream os = new FileOutputStream(tmp);//将文件目录中的文件放入输出流 //用输入流读取压缩文件中制定目录中的文件 InputStream in = zipFile.getInputStream(entry); int count = 0; while ((count = in.read())!=-1){//如有输入流可以读取到数值 os.write(count);//输出流写入 } os.close(); in.close(); } zin.closeEntry(); System.out.println(entry.getName()+"解压成功"); } zin.close(); } catch (IOException e) { e.printStackTrace(); } } }
做出相应更改:
import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * date:2019/7/26 * writed by yangtingting */ public class zipUncompress { /** * zip文件解压 * * @param inputFile 待解压文件夹/文件 * @param destDirPath 解压路径 */ public static void zipUncompress(String inputFile, String destDirPath) throws Exception { File srcFile = new File(inputFile);//获取当前压缩文件 // 判断源文件是否存在 if (!srcFile.exists()) { throw new Exception(srcFile.getPath() + "所指文件不存在"); } //开始解压 //构建解压输入流 ZipInputStream zIn = new ZipInputStream(new FileInputStream(srcFile)); ZipEntry entry = null; File file = null; while ((entry = zIn.getNextEntry()) != null) { if (!entry.isDirectory()) { file = new File(destDirPath, entry.getName()); if (!file.exists()) { new File(file.getParent()).mkdirs();//创建此文件的上级目录 } OutputStream out = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(out); int len = -1; byte[] buf = new byte[1024]; while ((len = zIn.read(buf)) != -1) { bos.write(buf, 0, len); } // 关流顺序,先打开的后关闭 bos.close(); out.close(); } } } public static void main(String[] args) { try { zipUncompress("D:\\ytt.zip", "D:\\ytt的解压文件\\"); } catch (Exception e) { e.printStackTrace(); } } }
完美运行!!!
3.2 zip解压完美实现
改进后的代码:
import java.io.*; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * date:2019/7/26 * writed by yangtingting */ public class zipUncompress { /** * zip文件解压 * @param inputFile 待解压文件夹/文件 * @param destDirPath 解压路径 */ public static void zipUncompress(String inputFile,String destDirPath) throws Exception { File srcFile = new File(inputFile);//获取当前压缩文件 // 判断源文件是否存在 if (!srcFile.exists()) { throw new Exception(srcFile.getPath() + "所指文件不存在"); } ZipFile zipFile = new ZipFile(srcFile);//创建压缩文件对象 //开始解压 Enumeration<?> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry) entries.nextElement(); // 如果是文件夹,就创建个文件夹 if (entry.isDirectory()) { String dirPath = destDirPath + "/" + entry.getName(); srcFile.mkdirs(); } else { // 如果是文件,就先创建一个文件,然后用io流把内容copy过去 File targetFile = new File(destDirPath + "/" + entry.getName()); // 保证这个文件的父文件夹必须要存在 if (!targetFile.getParentFile().exists()) { targetFile.getParentFile().mkdirs(); } targetFile.createNewFile(); // 将压缩文件内容写入到这个文件中 InputStream is = zipFile.getInputStream(entry); FileOutputStream fos = new FileOutputStream(targetFile); int len; byte[] buf = new byte[1024]; while ((len = is.read(buf)) != -1) { fos.write(buf, 0, len); } // 关流顺序,先打开的后关闭 fos.close(); is.close(); } } } public static void main(String[] args) { try { zipUncompress("D:\\ytt.zip","D:\\ytt的解压文件"); } catch (Exception e) { e.printStackTrace(); } } }
4 FileZip.class 实现.zip压缩与解压
完整代码:
import java.io.*; import java.util.zip.*; import java.util.zip.ZipEntry; /** * date: 2019/07/26 * writed by yangtingting */ public class FileZip { /** * zip文件压缩 * @param inputFile 待压缩文件夹/文件名 * @param outputFile 生成的压缩包名字 */ public static void ZipCompress(String inputFile, String outputFile) throws Exception { //创建zip输出流 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputFile)); //创建缓冲输出流 BufferedOutputStream bos = new BufferedOutputStream(out); File input = new File(inputFile); compress(out, bos, input,null); bos.close(); out.close(); } /** * @param name 压缩文件名,可以写为null保持默认 */ //递归压缩 public static void compress(ZipOutputStream out, BufferedOutputStream bos, File input, String name) throws IOException { if (name == null) { name = input.getName(); } //如果路径为目录(文件夹) if (input.isDirectory()) { //取出文件夹中的文件(或子文件夹) File[] flist = input.listFiles(); if (flist.length == 0)//如果文件夹为空,则只需在目的地zip文件中写入一个目录进入 { out.putNextEntry(new ZipEntry(name + "/")); } else//如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩 { for (int i = 0; i < flist.length; i++) { compress(out, bos, flist[i], name + "/" + flist[i].getName()); } } } else//如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入zip文件中 { out.putNextEntry(new ZipEntry(name)); FileInputStream fos = new FileInputStream(input); BufferedInputStream bis = new BufferedInputStream(fos); int len=-1; //将源文件写入到zip文件中 byte[] buf = new byte[1024]; while ((len = bis.read(buf)) != -1) { bos.write(buf,0,len); } bis.close(); fos.close(); } } /** * zip解压 * @param inputFile 待解压文件名 * @param destDirPath 解压路径 */ public static void ZipUncompress(String inputFile,String destDirPath) throws Exception { File srcFile = new File(inputFile);//获取当前压缩文件 // 判断源文件是否存在 if (!srcFile.exists()) { throw new Exception(srcFile.getPath() + "所指文件不存在"); } //开始解压 //构建解压输入流 ZipInputStream zIn = new ZipInputStream(new FileInputStream(srcFile)); ZipEntry entry = null; File file = null; while ((entry = zIn.getNextEntry()) != null) { if (!entry.isDirectory()) { file = new File(destDirPath, entry.getName()); if (!file.exists()) { new File(file.getParent()).mkdirs();//创建此文件的上级目录 } OutputStream out = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(out); int len = -1; byte[] buf = new byte[1024]; while ((len = zIn.read(buf)) != -1) { bos.write(buf, 0, len); } // 关流顺序,先打开的后关闭 bos.close(); out.close(); } } } public static void main(String[] args) { try { ZipCompress("D:\\Test", "D:\\TestbyYTT.zip"); ZipUncompress("D:\\ytt.zip","D:\\ytt的解压文件"); } catch (Exception e) { e.printStackTrace(); } } }
更多相关内容 -
哈夫曼实现文件压缩解压缩(c语言)
2019-01-23 17:04:47写一个对文件进行压缩和解压缩的程序,功能如下: ① 可以对纯英文文档实现压缩和解压; ② 较好的界面程序运行的说明。 介绍哈夫曼: 效率最高的判别树即为哈夫曼树 在计算机数据处理中,霍夫曼编码...写一个对文件进行压缩和解压缩的程序,功能如下:
① 可以对纯英文文档实现压缩和解压;
② 较好的界面程序运行的说明。
介绍哈夫曼:
效率最高的判别树即为哈夫曼树
在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。
例如,在英文中,e的出现机率最高,而z的出现概率则最低。当利用霍夫曼编码对一篇英文进行压缩时,e极有可能用一个比特来表示,而z则可能花去25个比特(不是26)。用普通的表示方法时,每个英文字母均占用一个字节,即8个比特。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。
霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的路径长度是从树根到每一结点的路径长度之和,记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明霍夫曼树的WPL是最小的。
文件压缩与解压
姓名: 范天祚
1 程序说明
1.1数据结构
哈夫曼树
1.2函数功能说明
printfPercent界面
compress()读取文件内容并加以压缩,将压缩内容写入另一个文档
uncompress()解压缩文件,并将解压后的内容写入新文件
1.3 程序编写的思路及流程
压缩:统计字符出现次数、将节点按出现次数排序、构造哈夫曼树、设置字符编码、读文件字符、按设置好的编码替换字符、写入存储文件
解压:读取文件各参数、转换成二进制码、按码求对应字符、写入存储文件
#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <stdio.h> #include <string.h> struct head { int b; //字符 long count; //文件中该字符出现的次数 long parent, lch, rch; //make a tree char bits[256]; //the huffuman code }; struct head header[512], tmp; //节点树 void printfPercent(int per) { int i = 0; printf("|"); for(i = 0; i < 10; i++) { if(i < per/10) printf(">"); else printf("-"); } printf("|已完成%d%%\n",per); } //函数:compress() //作用:读取文件内容并加以压缩 //将压缩内容写入另一个文档 int compress(const char *filename,const char *outputfile) { char buf[512]; unsigned char c; long i, j, m, n, f; long min1, pt1, flength; FILE *ifp, *ofp; int per = 10; ifp = fopen(filename, "rb"); //打开原始文件 if (ifp == NULL) { printf("打开文件失败:%s\n",filename); return 0; //如果打开失败,则输出错误信息 } ofp = fopen(outputfile,"wb"); //打开压缩后存储信息的文件 if (ofp == NULL) { printf("打开文件失败:%s\n",outputfile); return 0; } flength = 0; while (!feof(ifp)) { fread(&c, 1, 1, ifp); header[c].count ++; //读文件,统计字符出现次数 flength ++; //记录文件的字符总数 } flength --; header[c].count --; for (i = 0; i < 512; i ++) //HUFFMAN算法中初始节点的设置 { if (header[i].count != 0) header[i].b = (unsigned char) i; else header[i].b = -1; header[i].parent = -1; header[i].lch = header[i].rch = -1; } for (i = 0; i < 256; i ++) //将节点按出现次数排序 { for (j = i + 1; j < 256; j ++) { if (header[i].count < header[j].count) { tmp = header[i]; header[i] = header[j]; header[j] = tmp; } } } for (i = 0; i < 256; i ++) //统计不同字符的数量 { if (header[i].count == 0) break; } n = i; m = 2 * n - 1; for (i = n; i < m; i ++) { min1 = 999999999; for (j = 0; j < i; j ++) { if (header[j].parent != -1) continue; if (min1 > header[j].count) { pt1 = j; min1 = header[j].count; continue; } } header[i].count = header[pt1].count; header[pt1].parent = i; header[i].lch = pt1; min1 = 999999999; for (j = 0; j < i; j ++) { if (header[j].parent != -1) continue; if (min1 > header[j].count) { pt1 = j; min1 = header[j].count; continue; } } header[i].count += header[pt1].count; header[i].rch = pt1; header[pt1].parent = i; } for (i = 0; i < n; i ++) //构造HUFFMAN树,设置字符的编码 { f = i; header[i].bits[0] = 0; while (header[f].parent != -1) { j = f; f = header[f].parent; if (header[f].lch == j) { j = strlen(header[i].bits); memmove(header[i].bits + 1, header[i].bits, j + 1); header[i].bits[0] = '0'; } else { j = strlen(header[i].bits); memmove(header[i].bits + 1, header[i].bits, j + 1); header[i].bits[0] = '1'; } } } //下面的就是读原文件的每一个字符,按照设置好的编码替换文件中的字符 fseek(ifp, 0, SEEK_SET); //将指针定在文件起始位置 fseek(ofp, 8, SEEK_SET); //以8位二进制数为单位进行读取 buf[0] = 0; f = 0; pt1 = 8; printf("读取将要压缩的文件:%s\n",filename); printf("当前文件有:%d字符\n",flength); printf("正在压缩\n"); while (!feof(ifp)) { c = fgetc(ifp); f ++; for (i = 0; i < n; i ++) { if (c == header[i].b) break; } strcat(buf, header[i].bits); j = strlen(buf); c = 0; while (j >= 8) //当剩余字符数量不小于8个时 { for (i = 0; i < 8; i ++) //按照八位二进制数转化成十进制ASCII码写入文件一次进行压缩 { if (buf[i] == '1') c = (c << 1) | 1; else c = c << 1; } fwrite(&c, 1, 1, ofp); pt1 ++; strcpy(buf, buf + 8); j = strlen(buf); } if(100 * f/flength > per) { printfPercent(per); per += 10; } if (f == flength) break; } printfPercent(100); if (j > 0) //当剩余字符数量少于8个时 { strcat(buf, "00000000"); for (i = 0; i < 8; i ++) { if (buf[i] == '1') c = (c << 1) | 1; else c = c << 1; //对不足的位数进行补零 } fwrite(&c, 1, 1, ofp); pt1 ++; } fseek(ofp, 0, SEEK_SET); //将编码信息写入存储文件 fwrite(&flength,1,sizeof(flength),ofp); fwrite(&pt1, sizeof(long), 1, ofp); fseek(ofp, pt1, SEEK_SET); fwrite(&n, sizeof(long), 1, ofp); for (i = 0; i < n; i ++) { tmp = header[i]; fwrite(&(header[i].b), 1, 1, ofp); pt1++; c = strlen(header[i].bits); fwrite(&c, 1, 1, ofp); pt1++; j = strlen(header[i].bits); if (j % 8 != 0) //当位数不满8时,对该数进行补零操作 { for (f = j % 8; f < 8; f ++) strcat(header[i].bits, "0"); } while (header[i].bits[0] != 0) { c = 0; for (j = 0; j < 8; j ++) { if (header[i].bits[j] == '1') c = (c << 1) | 1; else c = c << 1; } strcpy(header[i].bits, header[i].bits + 8); fwrite(&c, 1, 1, ofp); //将所得的编码信息写入文件 pt1++; } header[i] = tmp; } fclose(ifp); fclose(ofp); //关闭文件 printf("压缩后文件为:%s\n",outputfile); printf("压缩后文件有:%d字符\n",pt1 + 4); return 1; //返回压缩成功信息 } //函数:uncompress() //作用:解压缩文件,并将解压后的内容写入新文件 int uncompress(const char *filename,const char *outputfile) { char buf[255], bx[255]; unsigned char c; char out_filename[512]; long i, j, m, n, f, p, l; long flength; int per = 10; int len = 0; FILE *ifp, *ofp; char c_name[512] = {0}; ifp = fopen(filename, "rb"); //打开文件 if (ifp == NULL) { return 0; //若打开失败,则输出错误信息 } //读取原文件长 if(outputfile) strcpy(out_filename,outputfile); else strcpy(out_filename,c_name); ofp = fopen(out_filename, "wb"); //打开文件 if (ofp == NULL) { return 0; } fseek(ifp,0,SEEK_END); len = ftell(ifp); fseek(ifp,0,SEEK_SET); printf("将要读取解压的文件:%s\n",filename); printf("当前文件有:%d字符\n",len); printf("正在解压\n"); fread(&flength, sizeof(long), 1, ifp); //读取原文件长 fread(&f, sizeof(long), 1, ifp); fseek(ifp, f, SEEK_SET); fread(&n, sizeof(long), 1, ifp); //读取原文件各参数 for (i = 0; i < n; i ++) //读取压缩文件内容并转换成二进制码 { fread(&header[i].b, 1, 1, ifp); fread(&c, 1, 1, ifp); p = (long) c; header[i].count = p; header[i].bits[0] = 0; if (p % 8 > 0) m = p / 8 + 1; else m = p / 8; for (j = 0; j < m; j ++) { fread(&c, 1 , 1 , ifp); f = c; _itoa(f, buf, 2); f = strlen(buf); for (l = 8; l > f; l --) { strcat(header[i].bits, "0"); //位数不足,执行补零操作 } strcat(header[i].bits, buf); } header[i].bits[p] = 0; } for (i = 0; i < n; i ++) { for (j = i + 1; j < n; j ++) { if (strlen(header[i].bits) > strlen(header[j].bits)) { tmp = header[i]; header[i] = header[j]; header[j] = tmp; } } } p = strlen(header[n-1].bits); fseek(ifp, 8, SEEK_SET); m = 0; bx[0] = 0; while (1) { while (strlen(bx) < (unsigned int)p) { fread(&c, 1, 1, ifp); f = c; _itoa(f, buf, 2); f = strlen(buf); for (l = 8; l > f; l --) { strcat(bx, "0"); } strcat(bx, buf); } for (i = 0; i < n; i ++) { if (memcmp(header[i].bits, bx, header[i].count) == 0) break; } strcpy(bx, bx + header[i].count); c = header[i].b; fwrite(&c, 1, 1, ofp); m ++; if(100 * m/flength > per) { printfPercent(per); per += 10; } if (m == flength) break; } printfPercent(100); fclose(ifp); fclose(ofp); printf("解压后文件为:%s\n",out_filename); printf("解压后文件有:%d字符\n",flength); return 1; //输出成功信息 } int main(int argc,const char *argv[]) { memset(&header,0,sizeof(header)); memset(&tmp,0,sizeof(tmp)); compress("测试文档.txt","测试文档.txt.zip"); uncompress("测试文档.txt.zip","测试文档.txt 解压后.txt"); system("pause"); return 0; }
2 功能展示
2.1 控制台显示
2.2 文件效果
开始时只有一个文件《测试文档.txt》:
打开《测试文档.txt》
《测试文档.txt》文件大小:
程序运行结束后多了两个文件:
以文本形式打开压缩二进制文件《测试文档.txt.zip》:
《测试文档.txt.zip》文件属性:
-
Java多文件压缩下载解决方案
2018-09-07 18:00:33Java多文件压缩下载解决方案 需求: 会员运营平台经过改版后页面增加了许多全部下载链接,上周上线比较仓促,全部下载是一个直接下载ZIP压缩文件的链接,每个ZIP压缩文件都是由公司运营人员将页面需要下载的文件...Java多文件压缩下载解决方案
需求:
会员运营平台经过改版后页面增加了许多全部下载链接,上周上线比较仓促,全部下载是一个直接下载ZIP压缩文件的链接,每个ZIP压缩文件都是由公司运营人员将页面需要下载的文件全部压缩成一个ZIP压缩文件,然后通过公司的交易运营平台上传至文件资料系统,会员运营平台则可以直接获取ZIP压缩文件地址进行下载
下面是一个页面示例:
需求分析:
通过上面需求和页面可以分析出,公司运营人员将页面全部需要下载的文件进行ZIP压缩后上传文件资料系统确实是一个紧急的解决方案,但是考虑到后面需求变更,页面需要下载的文件也会跟着变更,每次变更需求,公司运营人员都需要重新进行压缩文件,程序也需要进行相应的修改,这样对于程序的维护性不友好,站在使用系统的客户角度,每次都需要重新上传,因此临时解决方案不再符合软件的良好扩展性和操作方便,因此才有了对页面需要全部下载的文件使用程序压缩处理并下载。
解决思路:
第一步:前端传递Ids字符串
由于会员运营系统显示需要下载的文件是资料系统中的每条文件记录的Id,因此前端页面只需要将需要下载的所有文件Ids字符串(比如:'12,13,14')传递到后台即可.
第二步:后台处理
首先获取到前端传递的ids字符串,将其转换为Integer[]的ids数组,然后调用文件资料微服务根据id列表查询对应的文件记录(包含文件类型和文件地址路径等信息),获取到所有需要下载的文件路径后压缩成ZIP格式的文件进行下载。
具体实现压缩下载方案:
第一种:先压缩成ZIP格式文件,再下载
第二种:边压缩ZIP格式文件边下载(直接输出ZIP流)
前端具体实现代码:
由于全部下载是一个a链接标签,于是使用Ajax异步下载,后来功能实现后点击下载一点反应都没有,一度怀疑是后台出错,但是后台始终没有报错,在网上看了一下Ajax异步不能下载文件(也就是Ajax不支持流类型数据),具体原因可以百度https://blog.csdn.net/qq_16877261/article/details/54376430这篇博客,解释的还算是比较好的。后面会写一篇=文章详细分析Ajax异步下载解决方案。
接下来考虑使用form表单标签实现,最终配合使用input标签实现了前端传递ids列表的问题,点击a链接标签触发提交form标签即可。
在每一个需要下载的文件增加一个隐藏的input标签,value值是这个文件的id值
具体点击a链接标签提交表单的JS代码:
后端具体实现代码:
第一种方案实现:
第二种方案实现:
附上完整代码:
压缩下载Controller
package com.huajin.jgoms.controller.user; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.huajin.baymax.logger.XMsgError; import com.huajin.baymax.logger.Xlogger; import com.huajin.common.util.UUIDUtil; import com.huajin.exchange.domain.sys.FeFileCenter; import com.huajin.exchange.enums.sys.SysParamKey; import com.huajin.exchange.po.sys.SysParamPo; import com.huajin.jgoms.controller.HjBaseController; import com.huajin.jgoms.service.FeFileCenterService; import com.huajin.jgoms.service.SysParamService; import com.huajin.jgoms.util.CompressDownloadUtil; /** * 压缩下载文件 * * @author hongwei.lian * @date 2018年9月6日 下午6:29:05 */ @Controller @RequestMapping("/compressdownload") public class CompressDownloadController extends HjBaseController { @Autowired private FeFileCenterService feFileCenterService; @Autowired private SysParamService sysParamService; /** * 多文件压缩下载 * * @author hongwei.lian * @date 2018年9月6日 下午6:28:56 */ @RequestMapping("/downloadallfiles") public void downloadallfiles() { //-- 1、根据ids查询下载的文件地址列表 String ids = request().getParameter("ids"); if (StringUtils.isEmpty(ids)) { return ; } //-- 将字符串数组改变为整型数组 Integer[] idsInteger = CompressDownloadUtil.toIntegerArray(ids); List<FeFileCenter> fileCenters = feFileCenterService.getFeFileByIds(super.getExchangeId(), idsInteger); if (CollectionUtils.isNotEmpty(fileCenters) && ObjectUtils.notEqual(idsInteger.length, fileCenters.size())) { //-- 要下载文件Id数组个数和返回的文件地址个数不一致 return ; } //-- 2、转换成文件列表 List<File> files = this.toFileList(fileCenters); //-- 检查需要下载多文件列表中文件路径是否都存在 for (File file : files) { if (!file.exists()) { //-- 需要下载的文件中存在不存在地址 return ; } } //-- 3、响应头的设置 String downloadName = UUIDUtil.getUUID() + ".zip"; HttpServletResponse response = CompressDownloadUtil.setDownloadResponse(super.response(), downloadName); //-- 4、第一种方案: //-- 指定ZIP压缩包路径 // String zipFilePath = this.setZipFilePath(downloadName); // try { // //-- 将多个文件压缩到指定路径下 // CompressDownloadUtil.compressZip(files, new FileOutputStream(zipFilePath)); // //-- 下载压缩包 // CompressDownloadUtil.downloadFile(response.getOutputStream(), zipFilePath); // //-- 删除临时生成的ZIP文件 // CompressDownloadUtil.deleteFile(zipFilePath); // } catch (IOException e) { // Xlogger.error(XMsgError.buildSimple(CompressDownloadUtil.class.getName(), "downloadallfiles", e)); // } //-- 5、第二种方案: try { //-- 将多个文件压缩写进响应的输出流 CompressDownloadUtil.compressZip(files, response.getOutputStream()); } catch (IOException e) { Xlogger.error(XMsgError.buildSimple(CompressDownloadUtil.class.getName(), "downloadallfiles", e)); } } /** * 设置临时生成的ZIP文件路径 * * @param fileName * @return * @author hongwei.lian * @date 2018年9月7日 下午3:54:13 */ private String setZipFilePath(String fileName) { String zipPath = sysParamService.getCompressDownloadFilePath(); File zipPathFile = new File(zipPath); if (!zipPathFile.exists()) { zipPathFile.mkdirs(); } return zipPath + File.separator + fileName; } /** * 将fileCenters列表转换为File列表 * * @param fileCenters * @return * @author hongwei.lian * @date 2018年9月6日 下午6:54:16 */ private List<File> toFileList(List<FeFileCenter> fileCenters) { return fileCenters.stream() .map(feFileCenter -> { //-- 获取每个文件的路径 String filePath = this.getSysFilePath(feFileCenter.getFileTypeId()); return new File(filePath + feFileCenter.fileLink());}) .collect(Collectors.toList()); } /** * 获取文件类型对应存储路径 * * @param fileTypeId * @return * @author hongwei.lian * @date 2018年9月5日 下午2:01:53 */ private String getSysFilePath(Integer fileTypeId){ SysParamPo sysmParam = sysParamService.getByParamKey(SysParamKey.FC_UPLOAD_ADDRESS.value); String filePath = Objects.nonNull(sysmParam) ? sysmParam.getParamValue() : ""; return filePath + fileTypeId + File.separator; } }
压缩下载工具类
package com.huajin.jgoms.util; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.servlet.http.HttpServletResponse; import com.huajin.baymax.logger.XMsgError; import com.huajin.baymax.logger.Xlogger; /** * 压缩下载工具类 * * @author hongwei.lian * @date 2018年9月6日 下午6:34:56 */ public class CompressDownloadUtil { private CompressDownloadUtil() {} /** * 设置下载响应头 * * @param response * @return * @author hongwei.lian * @date 2018年9月7日 下午3:01:59 */ public static HttpServletResponse setDownloadResponse(HttpServletResponse response, String downloadName) { response.reset(); response.setCharacterEncoding("utf-8"); response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment;fileName*=UTF-8''"+ downloadName); return response; } /** * 字符串转换为整型数组 * * @param param * @return * @author hongwei.lian * @date 2018年9月6日 下午6:38:39 */ public static Integer[] toIntegerArray(String param) { return Arrays.stream(param.split(",")) .map(Integer::valueOf) .toArray(Integer[]::new); } /** * 将多个文件压缩到指定输出流中 * * @param files 需要压缩的文件列表 * @param outputStream 压缩到指定的输出流 * @author hongwei.lian * @date 2018年9月7日 下午3:11:59 */ public static void compressZip(List<File> files, OutputStream outputStream) { ZipOutputStream zipOutStream = null; try { //-- 包装成ZIP格式输出流 zipOutStream = new ZipOutputStream(new BufferedOutputStream(outputStream)); // -- 设置压缩方法 zipOutStream.setMethod(ZipOutputStream.DEFLATED); //-- 将多文件循环写入压缩包 for (int i = 0; i < files.size(); i++) { File file = files.get(i); FileInputStream filenputStream = new FileInputStream(file); byte[] data = new byte[(int) file.length()]; filenputStream.read(data); //-- 添加ZipEntry,并ZipEntry中写入文件流,这里,加上i是防止要下载的文件有重名的导致下载失败 zipOutStream.putNextEntry(new ZipEntry(i + file.getName())); zipOutStream.write(data); filenputStream.close(); zipOutStream.closeEntry(); } } catch (IOException e) { Xlogger.error(XMsgError.buildSimple(CompressDownloadUtil.class.getName(), "downloadallfiles", e)); } finally { try { if (Objects.nonNull(zipOutStream)) { zipOutStream.flush(); zipOutStream.close(); } if (Objects.nonNull(outputStream)) { outputStream.close(); } } catch (IOException e) { Xlogger.error(XMsgError.buildSimple(CompressDownloadUtil.class.getName(), "downloadallfiles", e)); } } } /** * 下载文件 * * @param outputStream 下载输出流 * @param zipFilePath 需要下载文件的路径 * @author hongwei.lian * @date 2018年9月7日 下午3:27:08 */ public static void downloadFile(OutputStream outputStream, String zipFilePath) { File zipFile = new File(zipFilePath); if (!zipFile.exists()) { //-- 需要下载压塑包文件不存在 return ; } FileInputStream inputStream = null; try { inputStream = new FileInputStream(zipFile); byte[] data = new byte[(int) zipFile.length()]; inputStream.read(data); outputStream.write(data); outputStream.flush(); } catch (IOException e) { Xlogger.error(XMsgError.buildSimple(CompressDownloadUtil.class.getName(), "downloadZip", e)); } finally { try { if (Objects.nonNull(inputStream)) { inputStream.close(); } if (Objects.nonNull(outputStream)) { outputStream.close(); } } catch (IOException e) { Xlogger.error(XMsgError.buildSimple(CompressDownloadUtil.class.getName(), "downloadZip", e)); } } } /** * 删除指定路径的文件 * * @param filepath * @author hongwei.lian * @date 2018年9月7日 下午3:44:53 */ public static void deleteFile(String filepath) { File file = new File(filepath); deleteFile(file); } /** * 删除指定文件 * * @param file * @author hongwei.lian * @date 2018年9月7日 下午3:45:58 */ public static void deleteFile(File file) { //-- 路径为文件且不为空则进行删除 if (file.isFile() && file.exists()) { file.delete(); } } }
测试
通过交易运营平台上传测试资料
登录会员运营平台进行下载
下载下来的ZIP格式为文件
解压后,打开文件是否可用:
总结:
这个过程中出现了很多问题,后面会有文章逐步分析出错和解决方案。
上述两种方案都行,但是为了响应速度更快,可以省略压缩成ZIP的临时文件的时间,因此采用了第二种解决方案。
-
java 实现多文件压缩加密 并重命名压缩文件对象
2021-01-07 15:44:25Java 多文件加密压缩 添加文件加密压缩工具包依赖 <!-- zip4j压缩工具 --> <dependency> <groupId>net.lingala.zip4j</groupId> <artifactId>zip4j</artifactId> <...Java 多文件加密压缩
添加文件加密压缩工具包依赖
<!-- zip4j压缩工具 --> <dependency> <groupId>net.lingala.zip4j</groupId> <artifactId>zip4j</artifactId> <version>1.3.2</version> </dependency>
话不多说,直接上干货
完整代码如下:
package com.rhtcms.cms.api.admin.main; import org.json.JSONObject; import org.springframework.stereotype.Controller; import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.util.Zip4jConstants; import java.io.*; import java.util.*; public class FileCompressionApiAct { /** * 复制压缩文件路径 ps:此路径必须为空文件夹,在压缩完成后此文件夹将被清空目录 */ private static String copyPath = "c:/Users/Administrator/Desktop/压缩测试/压缩测试作业复制"; private static long time = System.currentTimeMillis();//以时间戳作为文件名,防止重命名问题 /** * 压缩包路径: 路径+压缩包名称 eg: C:/Users/Administrator/Desktop/压缩测试/ + test.zip */ private static String zipPath = "C:/Users/Administrator/Desktop/压缩测试/" + time + ".zip"; /** * 可支持的压缩文件格式 */ private static String[] fileType = {"doc", "docx", "pdf", "txt"}; /** * @param filePath 压缩文件路径 * @param fileRename 压缩文件重命名名称 * @param password 加密密码 * @return * @Title: zipFilesAndEncrypt * @Description: 将指定路径下的文件压缩至指定zip文件,并以指定密码加密,若密码为空,则不进行加密保护 * @Author: 张庆裕 * @Date: 2021/01/04 */ //@RequestMapping("/fileCompression/list") public String zipFilesAndEncrypt(List<File> filePath, List<String> fileRename, String password) { /** * 压缩成功的文件数量 */ int successCount = 0; /** * 压缩失败的文件数量 */ int failCount = 0; /** * 返回数据 */ JSONObject ob = new JSONObject(); ArrayList<String> failFile = new ArrayList<>();//压缩失败的文件路径 ArrayList<String> failFilePath = new ArrayList<>();//路径错误的文件 ArrayList<File> filesToAdd = new ArrayList<>();//压缩路径的集合 //创建复制文件夹 File folder = new File(copyPath); if(!folder.exists()){//如果文件夹不存在 boolean mkdir = folder.mkdir();//创建文件夹 if(!mkdir){//系统未找到该路径 throw new RuntimeException("复制文件路径出错,请修改复制文件夹路径"); } }else{//文件夹存在 File[] listFiles = folder.listFiles(); if(listFiles.length > 0){//如何文件夹下存在目录则,停止压缩,防止删除其他文件 throw new RuntimeException("复制的文件夹不为空,请选择空文件夹!"); } } for (int i = 0; i < filePath.size(); i++) {//遍历压缩文件数据 File file = filePath.get(i);//获取原文件 if (!file.exists()) {//防止文件异常,首先再次确认文件路径是否存在 // 文件不存在 failCount++; failFilePath.add(file.getPath()); System.out.println("文件:" + file.getPath() + " 路径不存在!"); ob.put("failFilePath", failFilePath); } else {//文件存在 //获取原文件路径 String path = filePath.get(i).getPath(); //获取最后一个点的位置 int lastIndexOf = path.lastIndexOf("."); //获取文件后缀 eg: txt , doc , pdf .... String suffix = path.substring(lastIndexOf + 1); if (Arrays.asList(fileType).contains(suffix)) { //判断文件格式是否合格,合格添加至压缩文件中 //获取原文件名称 File oldName = new File(file.getPath()); //先复制文件 File newName = new File(copyPath + "/" + file.getName()); try { copyFile(oldName, newName); } catch (Exception e) { e.printStackTrace(); } //String path = newName.getPath();//获取复制文件的路径 String parentPath = newName.getParent();//获取复制出来的文件的父级目录 String reName = fileRename.get(i);//获取重命名的名称 newName.renameTo(new File(parentPath + "/" + reName));//重命名复制出来的文件 filesToAdd.add(new File(parentPath + "/" + reName));//将赋值出来的文件添加到压缩文件集合中 successCount++;//压缩成功文件数量+1 } else { failFile.add(file.getPath()); failCount++;//压缩失败文件数量+1 ob.put("filePath", failFile); System.out.println("该文件压缩失败:" + file.getPath() + " 文件格式错误!"); } } } //压缩配置 try { ZipParameters parameters = new ZipParameters(); parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);//压缩方式 //设置压缩级别 //DEFLATE_LEVEL_FASTEST - 最低压缩级别,但压缩速度更高 //DEFLATE_LEVEL_FAST - 低压缩级别,但压缩速度更高 //DEFLATE_LEVEL_NORMAL - 压缩水平速度之间的最佳平衡 //DEFLATE_LEVEL_MAXIMUM - 高压缩级别,但速度不佳 //DEFLATE_LEVEL_ULTRA - 最高压缩级别但速度较低 parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);//压缩级别 if (password != null && password!="") { parameters.setEncryptFiles(true);//设置压缩文件加密 parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);//加密方式 parameters.setPassword(password);//设置加密密码 } ZipFile zipFile = new ZipFile(zipPath);//创建压缩路径 zipFile.setFileNameCharset("gbk");//设置压缩编码 zipFile.addFiles(filesToAdd, parameters);//添加压缩文件并进行加密压缩 //压缩完成后清空复制的文件目录 deleteDir(copyPath); ob.put("zipPath", zipPath); ob.put("successCount", successCount); ob.put("failCount", failCount); } catch (ZipException e) { //清空复制的文件目录 deleteDir(copyPath); ob.put("unKnown", "未知异常,压缩失败!"); System.out.println("文件压缩出错"); e.printStackTrace(); } return ob.toString(); } /** * @Description: 文件复制 * @Param: resource 原文件路径 * @Param: target 新文件路径 * @return: * @Author: 张庆裕 * @Date: 2021/1/6 */ public void copyFile(File resource, File target) throws Exception { // 输入流 --> 从一个目标读取数据 // 输出流 --> 向一个目标写入数据 long start = System.currentTimeMillis(); // 文件输入流并进行缓冲 FileInputStream inputStream = new FileInputStream(resource); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); // 文件输出流并进行缓冲 FileOutputStream outputStream = new FileOutputStream(target); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); // 缓冲数组 // 大文件 可将 1024 * 2 改大一些,但是 并不是越大就越快 byte[] bytes = new byte[1024 * 2]; int len = 0; while ((len = inputStream.read(bytes)) != -1) { bufferedOutputStream.write(bytes, 0, len); } // 刷新输出缓冲流 bufferedOutputStream.flush(); //关闭流 bufferedInputStream.close(); bufferedOutputStream.close(); inputStream.close(); outputStream.close(); long end = System.currentTimeMillis(); System.out.println("复制文件:" + resource.getPath() + " 成功 耗时:" + (end - start) / 1000 + " s"); } /** * @Description: 清空复制压缩文件下的内容 * @Param: path 复制文件夹的路径 * @return: * @Author: 张庆裕 * @Date: 2021/1/6 */ public boolean deleteDir(String path) { File file = new File(path); if (!file.exists()) {//判断是否待删除目录是否存在 System.err.println("The dir are not exists!"); return false; } String[] content = file.list();//取得当前目录下所有文件和文件夹 for (String name : content) { File temp = new File(path, name); if (temp.isDirectory()) {//判断是否是目录 deleteDir(temp.getAbsolutePath());//递归调用,删除目录里的内容 temp.delete();//删除空目录 } else { if (!temp.delete()) {//直接删除文件 System.err.println("Failed to delete " + name); } } } return true; } /** * @Description: 文件压缩测试接口 * @Param: * @return: * @Author: 张庆裕 * @Date: 2021/1/7 */ public static void main(String[] args) { List<File> filePath = new ArrayList<>();//压缩文件路径 filePath.add(new File("C:/Users/Administrator/Desktop/压缩测试/yasuo/OA平台问题.docx")); filePath.add(new File("C:/Users/Administrator/Desktop/压缩测试/yasuo/OA平台问题1.docx")); filePath.add(new File("C:/Users/Administrator/Desktop/压缩测试/yasuo/OA平台问题2.docx")); filePath.add(new File("C:/Users/Administrator/Desktop/压缩测试/yasuo/OA平台问题3.docx")); filePath.add(new File("C:/Users/Administrator/Desktop/压缩测试/yasuo/邮箱1.md")); filePath.add(new File("C:/Users/Administrator/Desktop/压缩测试/yasuo/邮箱2.md")); List<String> fileRename = new ArrayList<>();//压缩文件重命名名称 fileRename.add("oa平台问题.docx"); fileRename.add("oa平台问题1.docx"); fileRename.add("oa平台问题2.docx"); fileRename.add("oa平台问题3.docx"); fileRename.add("邮箱副本1.md"); fileRename.add("邮箱副本2.md"); String password = "123456";//加密密码 //请在单元测试进行测试, 或者将方法改为 static 方法 //String result = zipFilesAndEncrypt(filePath, fileRename, password); //System.out.println(result); } }
效果如下:
在这里插入代码片
-
7-zip怎么把大文件压缩到最小
2021-06-05 06:06:117-Zip一款压缩软件,号称有着现今...7-zip软件怎么把大文件压缩到最小?1、先在本站下载并安装好7-zip软件,然后点击要压缩的文件右击先查看下源文件大小,简单记录下。在想要压缩保存的大文件上点击右键,选择7-zi... -
linux的tar命令详情;linux多个文件压缩打包到一个压缩文件
2020-06-21 20:13:11tar命令 可以用来压缩打包单文件...多个文件压缩打包 tar czvf my.tar.gz file1 file2,...(file*)(也可以给file*文件mv 目录在压缩) 单个目录压缩打包 tar czvf my.tar.gz dir1 多个目录压缩打包 tar czvf my.t -
基于Huffman树的文件压缩(详细)
2018-08-16 16:44:42文件压缩 开发平台:Visual Studio 2008 开发技术:哈夫曼树,堆排序 项目流程: (1)统计要压缩的文件中各字符出现的次数,利用数据结构中的小堆来构建Huffman树,每次在堆顶选出两个出现次数较小的字符先进行... -
HDFS文件压缩
2018-01-26 13:52:53减少储存文件所需空间,还可以降低其在网络上传输的时间。 hadoop下各种压缩算法的压缩比 压缩算法 原始文件大小 压缩后的文件大小 压缩速度 解压速度 gzip 8.3GB 1.8GB 17.5MB/s 58MB/s bzip2 8.3GB 1.1GB 2.4MB/s -
利用哈夫曼树实现文件压缩和解压缩
2018-08-20 08:20:05完成文件压缩与解压缩花了近一个星期的时间,期间,花了很遇到不少问题,花了很长时间去调试,最后完成了文本文件的压缩。通过调用库中的优先级队列实现哈夫曼树,基于哈夫曼树最终实现文件压缩。 ## 实现哈夫曼树... -
使用Java实现多个文件压缩打包
2017-10-17 22:46:45引言 在做项目的时候经常会涉及到文件的压缩,比如近期用Java Web做一个后台管理,后台有个导出功能,需要... 关于文件压缩,Java的java.util.zip包提供了这个功能。这个包下总共有20多个相关的类,下面介绍一 -
Huffman树与文件压缩的原理
2018-07-13 12:31:35Huffman树与文件压缩 1、Huffman树的简单介绍 Huffman树,又称为最优二叉树,是加权路径长度最短的二叉树。 下面,我要用一个简单的数组构造一棵Huffman树: a[]={0,1,2,3,4,5,6,7,8,9}; 从图片里我们可以... -
maven实现对js文件进行变量替换和文件压缩(2)
2019-11-22 10:27:02实现对js文件进行变量替换和文件压缩方式如下: 现在实现方式有两种:1.对js文件进行压缩,再对其进行变量替换。 2.对js文件进行变量替换,再对其进行压缩。 前文https://mp.csdn.net/postedit/103187480介绍了... -
Linux文件压缩命令
2019-04-28 10:55:33gzip/gunzip:主要是进行单个文件的压缩和解压缩的命令。 示例:gzip hello.txt #执行压缩hello.txt ls hello.txt.gz #查看文件信息 gunzip hello.txt.gz #解压文件命令 2、tar 命令 tar可以用来打包文件,还... -
用C++实现文件压缩
2016-08-15 00:28:43乍一听,这个文件压缩的名字貌似是很高大上的,其实,在数据结构中学完Huffman树之后,就可以理解这个东西其实不是那么的高不可攀。 文件压缩 所谓文件压缩,其实就是将对应的字符编码转换为另一种占据字节数少的... -
如何把一个文件压缩成几个固定大小的文件及解压缩
2017-12-25 11:39:54本文简单介绍了WinRAR如何把一个文件压缩成几个固定大小的文件以及如何解压这几个文件。 1、压缩 1 > 鼠标选中待压缩文件-右键-添加到压缩文件。 2 > 在弹出的“压缩文件和参数”窗口-切分压缩分卷... -
SpringBoot实现多文件压缩下载.zip
2020-03-01 21:01:14前言:有时候我们服务器生成多个文本文件。需要打包一次返回下载。例如:xml,word,excel try { response.setHeader("Content-Disposition", "attachment;filename=" + new String("压缩包名称.zip".getBytes("GB... -
linux大文件压缩及解压需要注意问题
2019-09-09 03:30:02压缩大文件,如何后台进行,如何防止终端关闭导致压缩停止,如何输出压缩过程日志,如何使用7z只打包,不压缩,分包压缩。 -
mp4视频文件压缩率大概是多大?
2020-10-30 11:38:05上一篇介绍了压缩率的计算方法:一帧1920*1080的画面有多少比特,需要多大带宽观看是才不会卡顿...压缩后视频大小 = 文件总大小 - 音频数据大小 = 142,540,800 byte- 31* 3 * 60 / 8 kb =141 826 560 B =138 502.5 K... -
基于哈夫曼编码的文本文件压缩与解压缩
2017-10-30 13:47:47基于哈夫曼编码实现文件压缩与解压缩,采用哈夫曼静态编码的方式,通过对数据进行两遍扫描,第一次统计出现的字符频次,进而构造哈夫曼树,第二遍扫描数据根据得到的哈夫曼树对数据进行编码。对于其中的加密编码只是... -
Mac下大文件压缩成多个包,即分卷压缩
2020-07-08 16:52:54最后才想到Mac用有自带命令可以处理压缩文件,于是在网上找了找,如下: 使用 zip 命令压缩文件 使用 zip 命令压缩文件,并结合 split 命令来分卷 格式:zip - <路径><文件名> | split -b <压缩文件... -
把音频文件压缩变小的方法
2019-10-06 16:01:54有时候一个音频文件比较大,传输以及使用很不方便,需要把文件压缩变小,这里就提供一种压缩的工具。 注意,压缩音频文件是以降低码率为代价的,可能会影响音频效果 码率计算公式 基本的算法是:【码率】(kbps)=... -
Linux文件压缩和打包
2018-05-27 13:47:04Linux文件压缩和打包一、压缩打包介绍常见压缩文件 ~Windows .rar .7z .zip ~Linux .zip .gz .bz2 .xz .tar.gz .tar.bz2 .tar.xz文件压缩的作用:1、节省空间 ... -
java多个文件压缩打包成zip下载
2018-12-21 14:53:53java多个文件压缩打包成zip下载 如果实现批量操作一些文件,使之压缩打包成zip下载? 具体实现步骤如下: 设置下载文件名编码 创建zip输出流ZipOutputStream 将需要下载的文件流循环写入ZipOutputStream 关闭各个流... -
java多个文件压缩成zip文件
2018-08-15 14:14:05文件压缩 */ private static void ZipFiles(java.io.File[] srcfile, java.io.File zipfile) { byte[] buf=new byte[1024]; ZipOutputStream out=null; try { out=new ZipOutputStream(new Fi... -
基于Huffman树的文件压缩原理及C语言实现(二)
2015-11-24 19:41:25在上文基于Huffman树的文件压缩原理及C语言实现(一)中已经介绍并实现了如何建立Huffman树,得到Huffman编码,这篇我们将会接着说。如何通过Huffman树,实现文件压缩。实现思路任何文件都可以看作是由字节组成的... -
HDFS的文件压缩格式
2018-08-01 12:43:59text命令),但hive只能用TEXTFILE格式的表加载,然后再insertoverwrite 到其他格式的表(比如SEQUENCEFILE表),如果hive其他格式的表想要直接加载压缩格式数据,需要重写INPUTFORMAT和OUTPUTFORMAT文件类。... -
哈夫曼树以及文件压缩的实现
2016-12-22 22:20:46从哈夫曼树到哈夫曼编码再到文件压缩,一步步讲解,一步步实现 -
SQLServer数据库文件压缩
2019-05-06 13:48:341.数据库文件压缩 点击数据库表右键-->任务-->收缩-->数据库 2.数据库日志文件压缩 --设置为简单模式 ALTER DATABASE 数据库名SET RECOVERY SIMPLE; GO -- 将日志文件压缩到1 MB. 数据库日志... -
如何使用7-Zip将一个大文件压缩成多个小的压缩包
2020-10-09 16:05:021、使用7-Zip将一个大文件压缩成多个小的压缩包; 2、使用7-Zip将多个小的压缩包,解压/合并成一个大文件。 1、使用7-Zip将一个大文件压缩成多个小的压缩包 1.1 确认电脑本地已经安装“7-Zip”...