精华内容
下载资源
问答
  • 它将清理LaTeX文件夹中的临时文件,并保留所有项目文件。 它是为Windows中的任何LaTeX项目开发的,并已针对TeXstudio项目进行了测试。 首先,将其解压缩到LaTeX项目文件夹中。 要运行,只需双击(仅Windows)。 联系...
  • 通过生成临时文件进行压缩打包下载 1.生成下载所需文件 根据自己情况,我是将字符串通过FileWriter项目路径的static中直接生成文件 public static void createFile(String string,String path,String name) ...

                              通过生成临时文件进行压缩打包下载

    1.生成下载所需文件

    根据自己情况,我是将字符串通过FileWriter在项目路径的static中直接生成文件

    public static void createFile(String string,String path,String name) throws IOException{
    		File file=new File(path);
    		if(!file.exists()){//如果文件夹不存在
    			file.mkdirs();//创建文件夹
    		}
    		FileWriter fileWriter= null;
    		fileWriter = new FileWriter(path+File.separator+name);
    		fileWriter.write(string);
    		fileWriter.flush();
    		fileWriter.close();
    	}

    2.生成一个临时zip压缩包,将所需文件读入压缩包

                    File fileZip = new File(AllPath.getZippath());
    				FileOutputStream outStream = new FileOutputStream(fileZip);
    				ZipOutputStream toClient = new ZipOutputStream(outStream);
    				Tool.compress(new File(AllPath.getFilePath()), toClient, "", true);
    				toClient.close();
    				outStream.close();
                    // 下载,并删除临时文件zip
    				Tool.downloadFile(AllPath.getFilename(),fileZip, response, true);

    工具类如下:采用的递归,一个个读写,,有些路径由于手动拼接的可能要少斜线,容易压缩出来没文件层次!

    /**
    	     * 递归压缩方法
    	     * @param sourceFile 源文件
    	     * @param zos        zip输出流
    	     * @param name       压缩后的名称
    	     * @param KeepDirStructure  是否保留原来的目录结构,true:保留目录结构; 
    	     *                          false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
    	     * @throws Exception
    	     */
    		public static void compress(File sourceFile, ZipOutputStream zos, String name,
    	            boolean KeepDirStructure) throws Exception{
    
    			byte[] buf = new byte[2 * 1024];
    	        if(sourceFile.isFile()){
    	            // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
    	            zos.putNextEntry(new ZipEntry(name));
    	            // copy文件到zip输出流中
    	            int len;
    	            FileInputStream in = new FileInputStream(sourceFile);
    	            while ((len = in.read(buf)) !=-1){
    	                zos.write(buf,0,len);
    	            }
    	            // Complete the entry
    	            zos.closeEntry();
    	            in.close();
    	        } else {
    	            File[] listFiles = sourceFile.listFiles();
    	            if(listFiles == null || listFiles.length == 0){
    	                // 需要保留原来的文件结构时,需要对空文件夹进行处理
    	                if(KeepDirStructure){
    	                    // 空文件夹的处理
    	                    zos.putNextEntry(new ZipEntry(name + File.separator));
    	                    // 没有文件,不需要文件的copy
    	                    zos.closeEntry();
    	                }              
    	            }else {
    	                for (File file : listFiles) {
    	                    // 判断是否需要保留原来的文件结构
    	                    if (KeepDirStructure) {
    	                        // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
    	                        // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
    	                        compress(file, zos, name + File.separator + file.getName(),KeepDirStructure);
    	                    } else {
    	                        compress(file, zos, file.getName(),KeepDirStructure);
    	                    }               
    	                }
    	            }
    	        }
    	    }

    3.下载生成的zip,根据需求是否删除

                    File fileZip = new File(AllPath.getZippath());
    				FileOutputStream outStream = new FileOutputStream(fileZip);
    				ZipOutputStream toClient = new ZipOutputStream(outStream);
    				Tool.compress(new File(AllPath.getFilePath()), toClient, "", true);
    				toClient.close();
    				outStream.close();
    				// 下载,并删除临时文件zip
    				Tool.downloadFile(AllPath.getFilename(),fileZip, response, true);
    			} catch (IOException e2) {
    				// TODO Auto-generated catch block
    				e2.printStackTrace();
    			} catch (Exception e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			} finally {
    				// 删除文件
    				Tool.delFolder(AllPath.getFilePath());
    			}
    		}

    工具类如下:

            下载:

     public static void downloadFile(String filename,File file, HttpServletResponse response, boolean isDelete) {
    	        try {
    	            // 以流的形式下载文件。
    	            BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
    	            byte[] buffer = new byte[fis.available()];
    	            fis.read(buffer);
    	            fis.close();
    	            // 清空response
    	            response.reset();
    	            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
    	            response.setContentType("application/octet-stream");
    	            if(filename==null||filename==""){
    	            	response.setHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes("UTF-8"),"ISO-8859-1"));
    	            }else{
    	            	response.setHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("UTF-8"),"ISO-8859-1"));
    	            }
    	            
    	            toClient.write(buffer);
    	            toClient.flush();
    	            toClient.close();
    	            if(isDelete)
    	            {
    	                file.delete();        //是否将生成的服务器端文件删除
    	            }
    	        }
    	        catch (IOException ex) {
    	            ex.printStackTrace();
    	        }
    	    }

        根据需求删除文件(上面已经删除了zip文件)

     /**
    	   * 删除文件夹  
    	   *2018年8月8日
    	   * @param folderPath
    	   *
    	   */
    	    public static void delFolder(String folderPath) {  
    	         try {  
    	            delAllFile(folderPath); //删除完里面所有内容  
    	            String filePath = folderPath;  
    	            filePath = filePath.toString();  
    	            java.io.File myFilePath = new java.io.File(filePath);  
    	            myFilePath.delete(); //删除空文件夹  
    	         } catch (Exception e) {  
    	           e.printStackTrace();   
    	         }  
    	    }
    	    /**
    	     * 删除文件及下
    	     *2018年8月8日
    	     * @param path
    	     * @return
    	     *
    	     */
    	    public static boolean delAllFile(String path) {  
    	        boolean flag = false;  
    	        File file = new File(path);  
    	        if (!file.exists()) {  
    	          return flag;  
    	        }  
    	        if (!file.isDirectory()) {  
    	          return flag;  
    	        }  
    	        String[] tempList = file.list();  
    	        File temp = null;  
    	        for (int i = 0; i < tempList.length; i++) {  
    	           if (path.endsWith(File.separator)) {  
    	              temp = new File(path + tempList[i]);  
    	           } else {  
    	               temp = new File(path + File.separator + tempList[i]);  
    	           }  
    	           if (temp.isFile()) {  
    	              temp.delete();  
    	           }  
    	           if (temp.isDirectory()) {  
    	              delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件  
    	              delFolder(path + "/" + tempList[i]);//再删除空文件夹  
    	              flag = true;  
    	           }  
    	        }  
    	        return flag;  
    	      }  

    综上所述:1.生成文件 2.将生成的文件刻入zip压缩包 3.删除zip和生成的文件

    我在本地springboot项目跑是没问题,之前百度的时候无意间搜到打包后部署到正式环境可能路径问题会出问题,仅供参考!

    希望路过的同学批评指正!!帮助进步!

    展开全文
  • java 生成zip压缩文件

    热门讨论 2010-06-21 08:51:27
    java 生成zip压缩文件 java 生成zip压缩文件
  • Java多文件压缩下载解决方案

    万次阅读 2018-09-07 18:00:33
    会员运营平台经过改版后页面增加了许多全部下载链接,上周上线比较仓促,全部下载是一个直接下载ZIP压缩文件的链接,每个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 实现压缩单个文件

    千次阅读 2018-07-29 22:13:59
    先来实现一个简单的单文件压缩,主要是为了解一下压缩需要使用到的流。。 效果: 说明:压缩实现使用ZipOutputStream 代码: package com.gx.compress; import java.io.BufferedInputStream; import java....

    先来实现一个简单的单文件压缩,主要是为了解一下压缩需要使用到的流。。

    效果:

    说明:压缩实现使用ZipOutputStream

    代码:

    package com.gx.compress;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipOutputStream;
    
    /**
    * @ClassName: CompressUtil 
    * @Description: 压缩单个文件
    * @author zhoujie 
    * @date 2018年7月29日 下午9:56:29 
    * @version V1.0
     */
    public class CompressUtil {
    	static String path = "F:\\图片\\"; //文件夹路径
    	
    	public static void main(String[] args) {
    		String filePath = path + "铜钱.jpg"; //图片名称
    		String outPath = path + "new.zip"; //压缩文件名称地址
    		zipUtil(filePath, outPath); //压缩
    	}
    	
    	public static void zipUtil(String filePath, String outPath){
    		//输入
    		File file = null;
    		FileInputStream fis = null;
    		BufferedInputStream bin = null;
    		DataInputStream dis = null;
    		//输出
    		File outfile = null;
    		FileOutputStream fos = null;
    		BufferedOutputStream bos = null;
    		ZipOutputStream zos = null;
    		ZipEntry ze = null;
    		try {
    			//输入-获取数据
    			file = new File(filePath);
    			fis = new FileInputStream(file);
    			bin = new BufferedInputStream(fis);
    			dis = new DataInputStream(bin); //增强
    			//输出-写出数据
    			outfile = new File(outPath);
    			fos = new FileOutputStream(outfile); 
    			bos = new BufferedOutputStream(fos, 1024); //the buffer size
    			zos = new ZipOutputStream(bos); //压缩输出流
    			ze = new ZipEntry(file.getName()); //实体ZipEntry保存
    			zos.putNextEntry(ze);
    			int len = 0;//临时文件
    			byte[] bts = new byte[1024]; //读取缓冲
    			while((len=dis.read(bts)) != -1){ //每次读取1024个字节
    				System.out.println(len);
    				zos.write(bts, 0, len); //每次写len长度数据,最后前一次都是1024,最后一次len长度
    			}
    			System.out.println("压缩成功");
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally{
    			try { //先实例化后关闭
    				zos.closeEntry();
    				zos.close();
    				bos.close();
    				fos.close();
    				dis.close();
    				bin.close();
    				fis.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	
    }
    
    

    以上仅为单个文件压缩,了解压缩流程。

    下面这个是支持 单文件 或 文件夹 压缩:

    java 实现压缩文件(单文件 或 文件夹)

    ok。

    展开全文
  • 哈夫曼编码实现文件压缩和解压

    万次阅读 多人点赞 2018-12-25 14:22:33
    哈夫曼编码是基于哈夫曼树实现的一种文件压缩方式。 哈夫曼树:一种带权路径最短的最优二叉树,每个叶子结点都有它的权值,离根节点越近,权值越小(根节点权值为0,往下随深度增加以此类推),树的带权路径等于...

    哈夫曼编码的概念

    哈夫曼编码是基于哈夫曼树实现的一种文件压缩方式。
    哈夫曼树:一种带权路径最短的最优二叉树,每个叶子结点都有它的权值,离根节点越近,权值越小(根节点权值为0,往下随深度增加依次加一),树的带权路径等于各个叶子结点的数值与其权值的乘积和。哈夫曼树如图:
    在这里插入图片描述
    从图中我们可以看出,数据都存放在叶子结点中,且为了达到树的带权路径最短,我们把数值大的节点放在靠近根的位置,这棵树的带权路径长度为:23+53+72+131=48。接下来我们为每个节点赋予哈夫曼编码,假设从根节点出发,到左子树获得编码0,到右子树获得编码1,这样我们可以得到D的编码是0,B的编码是10,C的编码是110,A的编码是111。离根越近的节点对应的编码越短,节点的数值越大。那么,如何把哈夫曼编码应用在文档的压缩上呢?我们记文件中字符出现的次数为节点的数值,出现次数最多的字符会分配到哈夫曼树的靠近根节点的地方,自然也就会获得较短的哈夫曼编码。于是我们通过这种方式,使得文档中的字符获得不同的哈夫曼编码,因为出现频次高的字符对应编码较短,所以从文档中获取的字节被哈夫曼编码替换之后,会获使得其占用的总存储空间变小,实现压缩的效果。

    实现哈夫曼压缩和解压的步骤详解

    建立哈夫曼树:
    1、使用IO流逐字节读取TXT文档。用一个数组(0~255,下标表示ASCII码)来保存不同字符出现的次数(对应位置加一)。
    2、建一个节点类,保存节点对象的信息。将数组每一位表示的字符和出现频次存入创建的节点,把所有节点存入一个链表。
    3、根据节点存储的频次值,对链表进行排序(从小到大)。
    4、从链表中取出并删除最小的两个节点,创建一个他们的父节点,父节点不存字符,值为那两个节点的和,把那两个节点分别作为其左子节点和右子节点,最后把这个父节点存入链表。再次排序,取出并删除最小的两个节点,生成父节点,再存入…以此类推,最终生成一棵哈夫曼树。
    5、对哈夫曼树进行遍历,使得叶子结点获得相应编码,同时把字符和它对应的哈夫曼编码存入HashMap。
    哈夫曼压缩的实现:
    1、再次读取原文档(之前第一次读取只是为了获取HashMap),根据HashMap中的字符与编码的键值对把整个文档转化为一串01码(此处可以用01字符串表示)。
    2、准备将数据写入要压缩的目录。首先把HashMap写入(如果压缩文件中没有HashMap的信息,在解压的时候将无法还原)。HashMap包括两个部分,一部分是key值(即字符),占一个字节,另一部分是01字符串编码,若转为字节表示,可能小于8位有可能大于8位(即长度不确定),我们在写入时必须明确每个01串占据的字节个数,再者,因为我们是以字节的形式写数据,写数据的时候总位数应是8的整数倍,需要对01串末尾补0。我们具体是这样写HashMap的:写键值对的数量(占一个字节);写key值(把字符转为ASCII值写入,占一个字节);写01码占几个字节(是补0后的字节数,此信息占一个字节);写补0情况(某位补0数,此处也占一个字节),写补零后的01码对应的若干字节。继续下一个键值对的写入…以此类推,直到整个HashMap的键值对都写完。
    3、刚才写的是编码信息,接下来准备把整个原文档转换得到的01串写入,这也是我们之后需要还原的信息。刚才的流没有关闭,我们是继续写入的。因为这依然会遇到最后一个字节不足8位的情况,我们需要补0并记录补0情况。先写整个文档的补0情况(一个字节),再把补0后的01串以每8位为一个字节写入压缩文件。
    4、以上操作便实现了哈夫曼压缩。另外需要注意的是,IO流的read()和write()方法是对字节进行读写,如果写的是int类型的数据,那么它表示的是相应的ASCII码值,如果写入的是字符,也是会转化为对应的字节的(0~255个字符都有对应的ASCII码,也都有对应的字节表示)。
    压缩格式如图
    在这里插入图片描述
    解压的实现:
    1、先读取第一个字节,即编码个数,确定了我们需要读多少组数据。
    2、开始正式读取键值对信息。读取key值,读取01码对应的字节数,读取补0情况,再读取表示01串的字节数据,去掉之前补的0,还原回0和1表示的字符串,即字符对应的哈夫曼编码,把读到的字符和哈夫曼编码保存在一个新建的HashMap中,需要注意的是此处key值存储为哈夫曼编码,value值存储为字符的信息。以此类推,直到读完所有键值对信息。
    3、读整个文件补0个数,读取文件字节数据,去掉补的0,得到之前存入的哈夫曼编码01字符串。
    4、确定希望解压的文件目录。逐位读取01字符串,将读到的位累加在一个临时字符串中,每读一位都拿这个临时字符串和HashMap进行对照,如果有对应key值,则获取对应字符信息写入流,把字符串置空,继续循环累加新的01串。最终读完后,解压目录中便得到了我们解压后的文件。

    代码实现

    1、节点类:

    public class Node<T> implements Comparable<Node<T>>{
    	private T data;
    	private int weight;
    	private Node<T> left;
    	private Node<T> right;	
    	public Node(T data,int weight)
    	{
    		this.data=data;
    		this.weight=weight;
    	}		
    	/**
    	 * 获取节点数据
    	 */
    	public String toString()
    	{
    		return "data:"+data+"   "+"weight:"+weight;
    	}
    	/**
    	 * 节点权值比较方法
    	 * @param o
    	 * @return
    	 */
    	public int compareTo(Node<T> o) {       
    		if(this.weight>o.weight)
    			return 1;
    		else if(this.weight<o.weight)
    			return -1;
    		return 0;
    	}	
    	public void setData(T data)
    	{
    		this.data=data;
    	}	
    	public void setWeight(int weight)
    	{
    		this.weight=weight;
    	}	
    	public T getData()
    	{
    		return data;
    	}	
    	public int getWeight()
    	{
    		return weight;
    	}	
    	public void setLeft(Node<T> node)
    	{
    		this.left=node;
    	}	
    	public void setRight(Node<T> node)
    	{
    		this.right=node;
    	}	
    	public Node<T> getLeft()
    	{
    		return this.left;
    	}	
    	public Node<T> getRight()
    	{
    		return this.right;
    	}		
    }
    

    2、mian方法入口及建树的方法

    public class HFMcompression {	
    	public static void main(String[] args)
    	{
    		HFMcompression hc = new HFMcompression();
    		File file  = new File("E:\\workspace\\mayifan\\src\\com\\myf\\HFMcompression1223\\data1.txt");//源文件地址	
    		FileOperation fo = new FileOperation();
    		int [] a = fo.getArrays(file);		
    		System.out.println(Arrays.toString(a)); //打印		
    		LinkedList<Node<String>> list = hc.createNodeList(a);//把数组的元素转为节点并存入链表			
    		for(int i=0;i<list.size();i++)
    		{
    			System.out.println(list.get(i).toString());
    		}
    		Node<String> root = hc.CreateHFMTree(list); //建树		
    		System.out.println("打印整棵树、、、、");
    		hc.inOrder(root); //打印整棵树
    		System.out.println("获取叶子结点哈夫曼编码");
    		HashMap<String,String> map = hc.getAllCode(root);//获取字符编码HashMap          
    		String str = fo.GetStr(map, file);
    		System.out.println("转化得到的01字符串:"+str);
    	        File fileCompress = new File("E:\\workspace\\mayifan\\src\\com\\myf\\HFMcompression1223\\data2.zip");//压缩文件地址
    		fo.compressFile(fileCompress,map,str);  //生成压缩文件
    		File fileUncompress = new File("E:\\workspace\\mayifan\\src\\com\\myf\\HFMcompression1223\\data3.txt");//压缩文件地址
    		fo.uncompressFile(fileCompress,fileUncompress);//解压文件至fileUncompress处
    	}	
    	/**
    	 * 把获得的数组转化为节点并存在链表中
    	 * @param arrays
    	 * @return
    	 */
    	public LinkedList<Node<String>> createNodeList(int[] arrays)
    	{
    		LinkedList<Node<String>> list = new LinkedList<>();
    		for(int i=0;i<arrays.length;i++)
    		{
    			if(arrays[i]!=0)
    			{
    				String ch = (char)i+"";
    				Node<String> node = new Node<String>(ch,arrays[i]); //构建节点并传入字符和权值
    				list.add(node); //添加节点
    			}
    		}
    		return list;
    	}		
    	/**
    	 * 对链表中的元素排序
    	 * @param list
    	 * @return
    	 */
    	public void sortList(LinkedList<Node<String>> list)
    	{
    		for(int i=list.size();i>1;i--)
    		{
    			for(int j=0; j<i-1;j++)
    			{
    				Node<String> node1 = list.get(j);
    				Node<String> node2 = list.get(j+1);
    				if(node1.getWeight()>node2.getWeight())
    				{
    					int temp ;					
    					temp = node2.getWeight();
    					node2.setWeight(node1.getWeight());
    					node1.setWeight(temp);
    					String tempChar;
    					tempChar = node2.getData();
    					node2.setData(node1.getData());
    				        node1.setData(tempChar);
    				        Node<String> tempNode = new Node<String>(null, 0);
    				        tempNode.setLeft(node2.getLeft());
    				        tempNode.setRight(node2.getRight());
    				        node2.setLeft(node1.getLeft());
    				        node2.setRight(node1.getRight());
    				        node1.setLeft(tempNode.getLeft());
    				        node1.setRight(tempNode.getRight());
    				}
    			}			
    		}
    	}				
    	/**
    	 * 建树的方法
    	 * @param list
    	 */
    	public Node<String> CreateHFMTree(LinkedList<Node<String>> list)
    	{
    		while(list.size()>1)
    		{
    			  sortList(list); //排序节点链表
    			  Node<String> nodeLeft = list.removeFirst();
    			  Node<String> nodeRight = list.removeFirst();
    			  Node<String> nodeParent = new Node<String>( null ,nodeLeft.getWeight()+nodeRight.getWeight());			  
    			  nodeParent.setLeft(nodeLeft);
    			  nodeParent.setRight(nodeRight);
    			  list.addFirst(nodeParent);
    		}
    		System.out.println("根节点的权重:"+list.get(0).getWeight());
    		return list.get(0);//返回根节点
    	}		
    	public HashMap<String, String> getAllCode(Node<String> root)
    	{
    		HashMap<String, String> map = new HashMap<>();
    		inOrderGetCode("", map, root);
    		return map;
    	}	
    	/**
    	 * 查询指定字符的哈夫曼编码(中序遍历)
    	 * @param code
    	 * @param st
    	 * @param root
    	 * @return
    	 */
    	public void inOrderGetCode(String code ,HashMap<String, String> map,Node<String> root)
    	{
    		if(root!=null)
    		{
    			inOrderGetCode(code+"0",map,root.getLeft());						
    			if(root.getLeft()==null&&root.getRight()==null)//存储叶子结点的哈夫曼编码
    			{		
    				System.out.println(root.getData());
    				System.out.println(code);
    				map.put(root.getData(), code);
    			}            
    			inOrderGetCode(code+"1",map,root.getRight());			
    		}				
    	}	
    	/**
    	 * 中序遍历输出整棵树
    	 * @param root
    	 * @return
    	 */
    	public void inOrder(Node<String> root)
    	{
    		if(root!=null)
    		{
    			inOrder(root.getLeft());			
    			if(root.getData()!=null)
                            System.out.println(root.getData());            
    			inOrder(root.getRight());			
    		}				
    	}	
    }
    

    3、文件操作类(包括文件压缩对外的接口和文件解压对外的接口):

    public class FileOperation {
    	FileOutputStream fos;//申明文件输出流对象
    	FileInputStream fis; //申明文件写入流对象		
    	/**
    	 * 通过文件获取数组的方法
    	 * @param str
    	 */
    	public int[] getArrays(File file)
    	{
    		int[] arrays = new int[256];
    		try{
    			FileInputStream fis = new FileInputStream(file);
    			int ascii=0;
    			while((ascii=fis.read())!=-1)
    			{
    				arrays[ascii]++;
    			}
    		    fis.close();
    		}catch(IOException e){
    			e.printStackTrace();
    		}
    		return arrays;
    	}		
    	/**
    	 * 读取文件获取01码
    	 */
    	public String GetStr(HashMap map,File file)
    	{
    		String str="";   //定义字符串储存01码
    		try{						
    			FileInputStream fis = new FileInputStream(file);
    			int value=0;			
    			while((value=fis.read())!=-1)
    			{
    				str+=map.get((char)value+"");  //取单字符对应的01码,累加到字符串中
    			}
    			fis.close();
    		}catch(IOException e)
    		{
    			e.printStackTrace();
    		}
    		return str;
    	}				
    	/**
    	 * 写HashMap到文件(写入编码个数+第一个key+第一个value所占字节数+value最后一个字节的补0情况+第一个value的若干字节+下一个key+。。。。)
    	 */
        public void writeHashMap(HashMap<String, String> map ,File file)
        {
        	int size = map.size(); //获取编码的个数,即HashMap中的键值对个数
        	String temp=""; //存放临时8位01字符串
        	int value=0; //存放01字符串转化得到的ASCII值
        	try{
    	    	fos = new FileOutputStream(file);
    	    	fos.write(size);  //写HashMap长度
                Set<String> keySet = map.keySet(); //获取HashMap存放key的容器
                java.util.Iterator<String> it = keySet.iterator();//通过容器获取迭代器
    	    	while(it.hasNext()) //迭代判断,有下一个key
    	    	{
    	    		String key = it.next(); //取出下一个key
    	    		String code = map.get(key); //取出code
    	    		fos.write(key.charAt(0)); //写key值
    	    		int a = code.length()/8;//能存满的字节数
    	    		int b = code.length()%8;//剩余的位数
    	    		int c =1; //值对应的存储的字节数
    	    		if(b==0) //无剩余位
    	    		{
    	    			c=a;
    	    			fos.write(c);  //写code的字节数
    	    			fos.write(0);  //写补0数,为0个
    	    		    for(int i=0;i<a;i++) //写code值
    	    		    {
    	    		    	temp="";
    	    		    	for(int j=0;j<8;j++) 
    	    		    	{
    	    		    		temp+=code.charAt(i*8+j);
    	    		    	}
    	    		    	value=StringToInt(temp);
    	    		    	fos.write(value); //逐一把code的每一位写出去
    	    		    }
    	    		}
    	    		else 
    	    		{
    	    		    c=a+1;
    	    		    fos.write(c); //写code的字节数
    	    		    fos.write(8-b); //写补0数
    	    		    for(int i=0;i<8-b;i++) //补0
    	    		    {
    	    		    	code+="0";
    	    		    }
    	    		    for(int i=0;i<c;i++)
    	    		    {
    	    		    	temp="";
    	    		    	for(int j=0;j<8;j++)
    	    		    	{
    	    		    		temp+=code.charAt(8*i+j);
    	    		    	}
    	    		    	value=StringToInt(temp);
    	    		    	fos.write(value); //逐一写code,包括补的0
    	    		    }	    	
    	    		}	    			    		
    	    	}
        	}catch(IOException e){
        		e.printStackTrace();
        	}
        }	
        /**
         * 把文档转化为的HFM编码写入文件
         */
    	public void writeHFMcode(String HFMcode)
    	{
    		int len = HFMcode.length();  //获取HFMcode长度
    		int a = len/8;   //求出完整的字节的数目
    		int b = len%8;   //求出剩余的位数
    		String temp = ""; //临时存放8位数据
    		int value = 0; //存放8位01转化得到的值
    		try
    		{
    			if(b==0)  //无不足八位的部分,不需要补0
    			{
    				fos.write(0); //写补0数
    				for(int i=0;i<a;i++)
    				{
    					temp="";
    					for(int j=0;j<8;j++)
    					{								
    						temp+=HFMcode.charAt(i*8+j);						
    					}
    					value=StringToInt(temp);
    					fos.write(value); //写HFMcode
    				}
    			}
    			else   //需要补0
    			{
    				int c = 8-b; //计算补0数
    				fos.write(c); //写补0数
    				for(int i=0;i<c;i++) //补0
    				{
    					HFMcode+="0";
    				}
    				for(int i=0;i<a+1;i++) 
    				{
    					temp="";
    					for(int j=0;j<8;j++)
    					{
    						temp+=HFMcode.charAt(i*8+j);
    					}
    					value=StringToInt(temp);
    					fos.write(value); //写HFMcode
    				}
    			}
    			fos.close(); //写完关闭资源
    		}
    		catch(IOException e)
    		{
    			e.printStackTrace();
    		}		
    	}	
    	/**
    	 * 把01字符串转化为ASCII码
    	 * @param temp
    	 * @return
    	 */
    	public int StringToInt(String temp)
    	{
    		int value=0;
    		for(int i=0;i<8;i++)
    		{
    			int x = temp.charAt(i)-48;
    			if(x==1)    //为1则累加入value
    			{
    				value+=Math.pow(2,7-i);  //表示2的(7-i)次方
    			}
    		}
    		return value;
    	}	
    	/**
    	 * 把数值转化为01字符串
    	 * @param value
    	 */
    	public String IntToString(int value)
    	{
    		String temp1=""; //存放反的字符串
    		String temp="";  //存放正的字符串
    		while(value>0) //逐渐取出各个二进制位数,字符串为反向的
    		{
    			temp1+=value%2;
    			value=value/2;
    		}		
    		for(int i=temp1.length()-1;i>=0;i--)
    		{
    			temp+=temp1.charAt(i);
    		}
    		return temp;
    	}	
    	/**
    	 * 把数值转化为01字符串,数值范围在0~255,01串不超过8位
    	 * @param value
    	 */
    	public String IntToStringEight(int value)
    	{
    		String temp1=""; //存放反的字符串
    		String temp="";  //存放正的字符串
    		int add=0;
    		while(value>0) //逐渐取出各个二进制位数,字符串为反向的
    		{
    			add++;
    			temp1+=value%2;
    			value=value/2;
    		}	
    		add=8-add;
    		for(int i=0;i<add;i++)//添0至8位
    		{
    			temp1+="0";
    		}
    		for(int i=temp1.length()-1;i>=0;i--) //反向的字符串获取正向的字符串
    		{
    			temp+=temp1.charAt(i);
    		}
    		return temp;
    	}						
    	/**
    	 * 对外部的接口,实现把压缩后的数据和信息写入压缩文件
    	 * @param fileCompress
    	 */
    	public void compressFile(File fileCompress,HashMap<String, String> map,String HFMcode)
    	{
    		writeHashMap(map, fileCompress);  //写HashMap的数据
    		writeHFMcode(HFMcode); //继续写HFMcode 01字符串
    	}	
    	/**
    	 * 解压获取HashMap
    	 * @param fileCompress
    	 */
    	public HashMap<String, String> readHashMap(File fileCompress)
    	{
    		HashMap<String, String> mapGet = new HashMap<>();
    		try
    		{
    			fis=new FileInputStream(fileCompress); 
    			int keyNumber = fis.read(); //读取key的数量
    			String key = ""; //HashMap的键值对
    			String code= ""; //未去0的字符串
    			String codeRZ="";//去0的字符串
    			int length=0; //表示还原后的字符串的理论长度,解决字符串前面的0的问题
    			int byteNum=1; //当前code占了几个字节
    			int addZero=0; //补0数
    			int value=0; //临时储值
    			int zeroLength=0;//code没有1的时候的字符串长度
    		    for(int i=0;i<keyNumber;i++)
    		    {
    		    	key = (char)fis.read()+""; //获取key值
    		    	byteNum=fis.read(); //获取code的字节数
    		    	addZero=fis.read(); //读取补0数量
    		    	if(addZero==0) //没有补0,是整字节数
    		    	{
    		    		for(int k=byteNum-1;k>=0;k--)
    		    		{
    		    			value+=fis.read()*(Math.pow(2, k*8));
    		    		}
    		    		code=IntToString(value);//把数值转为01code
    		    		value=0;//清零
    		    		length=8*byteNum-code.length();//计算在前面要补多少0
    		    		if(code.length()==0)  //若code内数字都为0,只要去掉尾部即可
    		    		{
    		    			zeroLength=length-addZero;  //计算有多少个0
    		    			for(int k=0;k<zeroLength;k++)
    		    			{
    		    				codeRZ+="0";
    		    			}
    		    		}
    		    		else    //code值不为0,补充前面的0,去掉后面的0
    		    		{
    			    		for(int k=0;k<length;k++)
    			    		{
    			    			codeRZ+="0";
    			    		}
    			    		for(int k=0;k<code.length()-addZero;k++)
    			    		{
    			    			codeRZ+=code.charAt(k);
    			    		}	
    		    		}
    		    	}
    		    	else  //有补0
    		    	{
    		    		for(int k=byteNum-1;k>=0;k--)
    		    		{
    		    			value+=fis.read()*(Math.pow(2, k*8));
    		    		}
    		    		code=IntToString(value);//把数值转为01code
    		    		value=0;//清0
    		    		length=8*byteNum-code.length();//计算在前面要补多少0	    		
    		    		if(code.length()==0)  //若code内数字都为0,只要去掉尾部即可
    		    		{
    		    			zeroLength=length-addZero;  //计算有多少个0
    		    			for(int k=0;k<zeroLength;k++)
    		    			{
    		    				codeRZ+="0";
    		    			}
    		    		}
    		    		else   //code值不为0,补充前面的0,去掉后面的0
    		    		{
    			    		for(int k=0;k<length;k++)
    			    		{
    			    			codeRZ+="0";
    			    		}
    			    		for(int k=0;k<code.length()-addZero;k++) //不要后面的0
    			    		{
    			    			codeRZ+=code.charAt(k);
    			    		}
    		    		}		    		
    		    	}		
    		    	mapGet.put(codeRZ , key ); //把读取到的键值对存入创建的HashMap
    		    	codeRZ=""; //清空
    		    }
    		}
    		catch(IOException e)
    		{
    			e.printStackTrace();
    		}
    		return mapGet;
    	}	
    	/**
    	 * 获取压缩文件中的数据,还原哈夫曼编码01串
    	 */
    	public String readHFMStr()
    	{
    		String str1=""; //存放获取到的直接的01字符串
    		String str=""; //存放去掉补0的字符串
    		int value=0;
    		String temp="";
    		try{
    			int addZero = fis.read(); //读取整个文件的补0个数			
    			while((value=fis.read())!=-1)
    			{
    				temp=IntToStringEight(value); //把每个字节的数据转化为八位的01
    				str1+=temp;       
    			}
    			if(addZero!=0) //有补0,获取补0前的字符串
    			{
    				for(int i=0;i<str1.length()-addZero;i++) //补0的部分不赋值
    					str+=str1.charAt(i)+""; 
    				return str;  
    			}
    			fis.close();
    		}
    		catch(IOException e)
    		{
    			e.printStackTrace();
    		}	
    		return str1;
    	}	
    	/**
    	 * 写入文件的保存路径(写文件)
    	 * @param str
    	 * @param mapGet
    	 * @param fileCompress
    	 */
    	public void writeFile(String str , HashMap<String, String> mapGet,File fileCompress)
    	{
    		try
    		{
    			fos = new FileOutputStream(fileCompress); //获取文件输出流
    			int len = str.length();//获取01串的长度
    			String temp=""; //临时存放段的01字符串
    			for(int i=0;i<len;i++)
    			{
    				temp+=str.charAt(i);
    				if(mapGet.containsKey(temp))
    				{
    					fos.write(mapGet.get(temp).charAt(0)); //一个字符的字符串转字符然后写出
    					temp="";					
    				}
    			}
    			fos.close();
    		}
    		catch(IOException e)
    		{
    			e.printStackTrace();
    		}
    	}	
    	/**
    	 * 对外部的接口,实现解压文件,获取HashMap和文件内容
    	 * @param fileCompress,压缩文件目录
    	 * @param fileUncompress,解压到的目录
    	 */
    	public void uncompressFile(File fileCompress,File fileUncompress)
    	{
    		HashMap<String, String> mapGet = readHashMap(fileCompress); //获取哈希表
    		String str = readHFMStr();  //获取01字符串
    		writeFile(str,mapGet,fileUncompress);  //写文件到保存路径
    	}				
    }
    

    压缩、解压效果

    1、压缩文件所占内存小于原文件,解压后的文件和原文件大小相同。如图data1是原文件,data2是压缩文件,data3的解压后的文件。我们可以发现压缩后的压缩包所占内存3KB<5KB。
    在这里插入图片描述
    2、原文件和解压后的文件的内容展示:
    data1.txt:
    在这里插入图片描述
    data3.txt:
    在这里插入图片描述
    解压后txt的信息和原文件完全一致。

    展开全文
  • 最近写项目接口,涉及到文件下载、打包压缩下载,单个文件下载还是比较简单的,多文件下载涉及到打包和压缩知识,之前也没做过,写篇博客做个简单的记录一下。闲言少叙,上代码: 如下代码是精简过后的测试代码,...
  • 什么是压缩文件/压缩包?

    万次阅读 2020-08-12 14:13:24
    计算机是以二进制的形式来储存所有的文件的,也就是00000001111111类似这种形式,压缩文件就会以一种类似编码的形式来储存这些文档,比如四个0连一起,压缩文件就会以4x0的形式储存计算机里,当然实际的压缩比这...
  • 本文介绍的方法中会将这些压缩文件在后台一个临时目录 /tmp 中进行解压缩。重启系统后,/tmp 目录的内容将被清空。 进一步讨论之前,这里先解释一下归档和压缩文件。 归档 是将多个文件或文件夹组合成一个文件的...
  • 提示:只需修改MyZip程序,将原先读取要加入的文件的内容后直接写到压缩文件中的代码,修改为先将要加入的文件压缩为一个临时文件后,再将压缩后的文件合并到原压缩文件中。压缩要加入的文件时,可调用LZARI类的...
  • Linux解、压缩文件及权限命令

    千次阅读 2019-10-15 19:59:58
    tar 解压缩命令中的参数分别代表什么意思? 建立压缩档案 : -c 解压 : -x 查看内容: -t 向压缩归档文件末尾追加文件: -r 更新原压缩包中的文件: -u 必选参数 ...
  • 利用哈夫曼树实现文件压缩

    千次阅读 2017-02-27 10:51:49
    3.根据字符的哈夫曼编码进行转换、压缩,然后创建压缩文件。 4.读取压缩文件,读出哈夫曼编码和字符的对照表。解压缩。 数据结构的设计: 1.保存字符次数和字符的数据结构 struct _symbol{ char charac
  •   程序员做web等项目的时候,往往都需要添加文件上传、下载、删除的功能,有时是单文件,有时多文件批量 操作,而这些功能的代码程序员可以自己收藏起来当成工具使用,这样,程序员进行程序设计的时候就会...
  • 工具类--Java生成csv文件压缩

    千次阅读 2019-06-25 19:26:54
    csv文件支持excel文件格式打开,但是却不需要poi的支持,文件生成更加简单,方便,项目中需要用到csv文件,做下记录: 1.生成csv文件: /** * <生成csv文件> * * @param fileName fileName * @param ...
  • Java实现将文件或者文件夹压缩成zip

    千次阅读 2018-09-19 10:11:34
    但未经作者同意必须保留此段声明,且文章页面明显位置给出原文链接! 最近碰到个需要下载zip压缩包的需求,于是我网上找了下别人写好的zip工具类。但找了好多篇博客,总是发现有bug。因此就自己来写了个工具类...
  • Java导出zip压缩文件

    千次阅读 2019-01-18 15:20:48
    这里需要说明的是我的项目需要各种不同文件导出,所以进行压缩,当项目上线的时候,我们是没有本地电脑路径的,所以压缩路径我选择项目的根目录下,全部压缩成功,调用删除,进行删除,这样虚拟机上也可以进行...
  • 通常来说,我们查看归档或压缩文件的内容,需要先进行解压缩,然后再查看,比较麻烦。今天给大家介绍 10 不同方法,能够让你轻松地未解压缩的情况下查看归档或压缩文件的内容。...
  • 一、存储 行存储的特点: 查询满足条件的一整行数据的时候,列存储则需要去每个聚集的字段找到对应的...每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。 Hive中常用的存储格式: 1....
  • Java实现文件下载Zip压缩

    千次阅读 2021-03-25 16:24:49
    目录 一、 概述 二、代码功能实现 一、 概述 ... 构建一个Zip文件输出流(临时文件Zip) 从服务读取文件流放入Zip文件输出流 把临时文件Zip写入OutputStream 关闭资源 1. controller /** *
  • Java操作zip压缩和解压缩文件工具类

    千次阅读 2017-12-04 13:40:15
    System.out.println(" 开始压缩文件[" + srcFile.getName() + "]"); if( !"".equals(path) && ! path.endsWith(File.separator)){ path += File.separator ; } if (!srcFile.exists()) {//测试此抽象路径名定义...
  • * 从OSS服务中下载所需文件到本地临时文件,并将文件以ZIP格式进行压缩 * @param endpoint oss对外服务的域名 * @param accessKeyId 用户身份认证标识 * @param accessKeySecret 用于加密签名字符串,oss用来...
  • Python压缩解压zip,Django下载zip文件

    千次阅读 2019-09-05 20:07:53
    python压缩文件 使用zipfile import zipfile def convert_zip(zip_path, save_path): ''' # zip_path 要压缩文件的路径 # save_path 文件压缩后保存的路径 ''' local_path = os.path.join(zip_path, "x.xls")...
  • Linux命令之搜索.gz压缩文件包含关键字的内容 前言 常用命令 参考链接 前言 场景介绍 服务器上的日志大多数都是对历史日志进行tar.gz压缩(例如:超过一定大小或者定时压缩),当我们需要临时查看历史日志,且又不想...
  • 看起来很简单的需求,我是这么想的,将需要的文件列表作为配置文件,通过shell脚本,依次读取该配置文件,并get到堡垒机上,全部下载完成后,将该目录打包压缩,上传到SFTP上,测试环境上登陆SFTP,下载后,上传到...
  • SpringMVC下压缩文件下载

    千次阅读 热门讨论 2017-02-26 21:28:03
    最近做文件下载的功能,由于下载的是图片,内容... 1)服务器端建立一个临时压缩文件  2)找到文件路径,用JDK自带的API进行文件压缩  3)将zip文件下载,文件流输出  4)删除服务器端临时文件  文件下载:
  • 基于哈夫曼编码的文件压缩解压

    千次阅读 多人点赞 2016-05-31 14:51:40
    这个程序是研一上学期的课程大作业。当时,跨专业的我只有一点 C 语言和数据结构基础,为此,我查阅了不少资料,再加上自己的思考和分析,实现后不断调试、测试和完善,耗时一...名称:基于哈夫曼编码的文件压缩解压
  • 分块压缩是一项特别常用的功能,那么Mac系统上如何对文件(文件夹)进行分块压缩呢?使用BetterZip软件可以做到这一点,下面小编放上教程。 点击免费下载betterzip软件 点击进入betterzip中文网站了解更多软件...
  • sftp文件上传下载改名压缩解压

    千次阅读 2017-11-21 11:54:25
    //移动到临时目录并打包 startfile .renameTo (new File(local+ "\\" +startfile .getName ())) ; } //压缩 String zipoutpath = local+ ".zip" ; ZipCompress .zipFiles (new File(local) .listFiles (), ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 136,774
精华内容 54,709
关键字:

压缩文件临时文件在哪