精华内容
下载资源
问答
  • 在使用slf4j的logback实现,使用TimeBasedRollingPolicy根据时间滚动日志策略并使用RollingFileAppender进行日志滚动,多进程共用同一个日志文件,会出现较多xxxxxx.tmp文件未删除的情况。 出现tmp文件的条件:...

    在使用slf4j的logback实现时,使用TimeBasedRollingPolicy根据时间滚动日志策略并使用RollingFileAppender进行日志滚动,多进程共用同一个日志文件时,会出现较多xxxxxx.tmp文件未删除的情况。

    出现tmp文件的条件: 使用TimeBasedRollingPolicy/RollingFileAppender配置,并启用压缩,并配置的<file></file>标签名称与滚动名称模板不同(如打印日志时文件名为demo.log,归档时文件名demo.2019-12-12.log.gz),并且单应用启动多实例共用一个日志文件作为输出,例如:

    	<appender name="File"
    		class="ch.qos.logback.core.rolling.RollingFileAppender">
    		<file>${LOG_HOME}/demo.log</file>
    		<rollingPolicy
    			class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    			<FileNamePattern>${LOG_HOME}/demo.log.%d{yyyy-MM-dd}.log.gz
    			</FileNamePattern>
    			<MaxHistory>30</MaxHistory>
    		</rollingPolicy>
    		<encoder
    			class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    			<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
    		</encoder>
    	</appender>

    多进程将日志输出到同一个日志文件logback是允许的,仅输出也不会出现问题,但是当归档时,多个进程同时归档,原文件与目标文件(归档文件)名称不同时,会首先关闭输出流,然后将原日志文件rename为xxx.timestamp.tmp,然后读取tmp文件输出到目标归档文件,此时如果是多进程,其他进程那一时刻很有可能没有关闭输出流,所以tmp文件内容一致再增加,并且当其他进程开始归档时也会同样的流程创建tmp文件,然是创建tmp文件后,后续判断归档文件已存在,直接返回了,导致tmp文件未被删除。

    解决方法:

    1. 不压缩(但是多进程也存在问题,日志输出混乱,某个时间点的日志可能出现在上一个时间点日志文件内)

    2. 删除<file>xxx</file>标签,此时产生的日志文件名与归档文件名相同(归档文件后缀.gz/zip),不需要创建临时文件,直接压缩原文件,压缩完毕会删除原文件(可能会丢日志,因为其他进程还在往里面写)

    3. 多进程配置不同的logback配置文件,日志分开存储

    4. appender标签启用<prudent>true</prudent>, logback允许多jvm使用同一个log日志,启用该标志会加锁,在日志输出每秒<100条时性能影响不大,但是不使用该功能要比使用该功能日志性能高3倍左右。局限性就是不能日志使用压缩功能,不能使用<file>标签指定日志文件名,详细参考:prudent   prudentWithRolling

    源码解析如下:

        //RollingFileAppender
        public void rollover() {
            //加锁,统一进程同一时刻只会有一个归档操作
            lock.lock();
            try {
                //关闭日志输出流
                this.closeOutputStream();
                //归档,删除过期文件(如保留30天内,则超过30天的文件被删除)
                attemptRollover();
                //重新创建或打开日志文件,并设置输出流
                attemptOpenFile();
            } finally {
                lock.unlock();
            }
        }
        
        private void attemptRollover() {
            try {
                //调用滚动策略滚动归档日志
                rollingPolicy.rollover();
            } catch (RolloverFailure rf) {
                addWarn("RolloverFailure occurred. Deferring roll-over.");
                // we failed to roll-over, let us not truncate and risk data loss
                this.append = true;
            }
        }
       //TimeBasedRollingPolicy 1.1.7
       public void rollover() throws RolloverFailure {
    
            //该方法被执行时,会认为日志文件为已关闭
            String elapsedPeriodsFileName = timeBasedFileNamingAndTriggeringPolicy.getElapsedPeriodsFileName();
    
            String elapsedPeriodStem = FileFilterUtil.afterLastSlash(elapsedPeriodsFileName);
            //压缩模式,FileNamePattern标签对应的文件后缀,.gz .zip,否则不压缩
            if (compressionMode == CompressionMode.NONE) {
                //获取file标签是否配置,如果配置了,则将原文件重命名为归档文件
                if (getParentsRawFileProperty() != null) {
                    renameUtil.rename(getParentsRawFileProperty(), elapsedPeriodsFileName);
                } // else { nothing to do if CompressionMode == NONE and parentsRawFileProperty == null }
            } else {
                //file标签没有配置,直接将原文件压缩为目标归档文件
                if (getParentsRawFileProperty() == null) {
                    compressionFuture = compressor.asyncCompress(elapsedPeriodsFileName, elapsedPeriodsFileName, elapsedPeriodStem);
                } else {
                //配置了file标签则需要先重命名为tmp,然后读取tmp输出到归档压缩文件
                    compressionFuture = renamedRawAndAsyncCompress(elapsedPeriodsFileName, elapsedPeriodStem);
                }
            }
            //删除过期文件
            if (archiveRemover != null) {
                Date now = new Date(timeBasedFileNamingAndTriggeringPolicy.getCurrentTime());
                cleanUpFuture = archiveRemover.cleanAsynchronously(now);
            }
        }
        //重命名并压缩归档
        Future<?> renamedRawAndAsyncCompress(String nameOfCompressedFile, String innerEntryName) throws RolloverFailure {
            String parentsRawFile = getParentsRawFileProperty();
            //tmp文件名
            String tmpTarget = parentsRawFile + System.nanoTime() + ".tmp";
            //重命名
            renameUtil.rename(parentsRawFile, tmpTarget);
            //异步压缩
            return compressor.asyncCompress(tmpTarget, nameOfCompressedFile, innerEntryName);
        }
        //Compressor 异步压缩
        public Future<?> asyncCompress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) throws RolloverFailure {
            //参数:原文件,归档文件
            CompressionRunnable runnable = new CompressionRunnable(nameOfFile2Compress, nameOfCompressedFile, innerEntryName);
            ExecutorService executorService = context.getExecutorService();
            //提交线程池
            Future<?> future = executorService.submit(runnable);
            return future;
        }
        // 压缩
        public void compress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) {
            //gz zip压缩
            switch (compressionMode) {
            case GZ:
                gzCompress(nameOfFile2Compress, nameOfCompressedFile);
                break;
            case ZIP:
                zipCompress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName);
                break;
            case NONE:
                throw new UnsupportedOperationException("compress method called in NONE compression mode");
            }
        }
    
        private void gzCompress(String nameOfFile2gz, String nameOfgzedFile) {
            File file2gz = new File(nameOfFile2gz);
            //原文件不存在直接返回,注意此时tmp文件没有被删除
            if (!file2gz.exists()) {
                addStatus(new WarnStatus("The file to compress named [" + nameOfFile2gz + "] does not exist.", this));
    
                return;
            }
            //如果没有gz后缀,则加个后缀
            if (!nameOfgzedFile.endsWith(".gz")) {
                nameOfgzedFile = nameOfgzedFile + ".gz";
            }
            //归档文件
            File gzedFile = new File(nameOfgzedFile);
            //归档文件是否存在,已存在直接返回,注意此时tmp文件没有被删除
            if (gzedFile.exists()) {
                addWarn("The target compressed file named [" + nameOfgzedFile + "] exist already. Aborting file compression.");
                return;
            }
    
            addInfo("GZ compressing [" + file2gz + "] as [" + gzedFile + "]");
            createMissingTargetDirsIfNecessary(gzedFile);
    
            BufferedInputStream bis = null;
            GZIPOutputStream gzos = null;
            //读取tmp文件输出到归档文件
            try {
                bis = new BufferedInputStream(new FileInputStream(nameOfFile2gz));
                gzos = new GZIPOutputStream(new FileOutputStream(nameOfgzedFile));
                byte[] inbuf = new byte[BUFFER_SIZE];
                int n;
    
                while ((n = bis.read(inbuf)) != -1) {
                    gzos.write(inbuf, 0, n);
                }
    
                bis.close();
                bis = null;
                gzos.close();
                gzos = null;
                //删除临时文件,这个地方有个问题如果上面抛异常了,tmp文件依旧删不掉
                //1.3.0版本该部分移到了try-catch后面
                if (!file2gz.delete()) {
                    addStatus(new WarnStatus("Could not delete [" + nameOfFile2gz + "].", this));
                }
            } catch (Exception e) {
                addStatus(new ErrorStatus("Error occurred while compressing [" + nameOfFile2gz + "] into [" + nameOfgzedFile + "].", this, e));
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        // ignore
                    }
                }
                if (gzos != null) {
                    try {
                        gzos.close();
                    } catch (IOException e) {
                        // ignore
                    }
                }
            }
        }

     

    展开全文
  • 在使用LogBack打印日志,并根据每天和自定义大小拆分压缩文件时,**出现上百G的tmp文件,不会自动删除,另外,出现tmp没有删除的情况压缩文件里面的文件是空的。** 请问是什么情况,是否可以优化logback的配置...

    在使用LogBack打印日志,并根据每天和自定义大小拆分压缩文件时,**出现上百G的tmp文件,不会自动删除,另外,出现tmp没有删除的情况时,压缩文件里面的文件是空的。**
    请问是什么情况,是否可以优化logback的配置。
    当前应用的每日日志量大概在10G.
    图片说明

       <!-- 文件输出 -->
      <appender name="file_log"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/log.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
          <fileNamePattern>${BACKUP}/log%d{yyyy-MM-dd}-%i.log.zip
          </fileNamePattern>
          <maxHistory>30</maxHistory>
          <timeBasedFileNamingAndTriggeringPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>500MB</maxFileSize>
          </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
          <charset>${CHARSET}</charset>
          <pattern>${PATTERN_DEF}</pattern>
        </encoder>
      </appender>

     

    升级至logback到1.1.6以上即可解决。

     

    转载于:https://my.oschina.net/yizhichao/blog/1576247

    展开全文
  • HDFS文件压缩

    千次阅读 2020-01-04 18:06:11
    在这种情况下,MapReduce会采用正确的做法,它不会尝试切分gzip压缩文件,因为它知道输入的gzip压缩文件(通过文件扩展名看出)且gzip不持支切分。这是可行的,但 牺牲了数据的本地性 :一个map任务处理8个HDFS块...

    前言

    新搭建的集群,需要进行各种测试,于是让一个同事导入一些测试数据,大约1.4T左右。我进行了一个简单的hive测试

    //故意增加shuffle
    SELECT DISTINCT(COUNT id) FROM test_table;
    

    谁知道…就这么一个简单的SQL,半个小时过去后,仍然没有出结果

    追查原因

    原来同事从ftp拉取过来的数据是gzip格式的,他直接导入到Hive表中…,而gzip格式的数据是不可切分的

    如何理解不可切分

    为了进一步理解gzip等不可切分的压缩格式,我做了个测试

    • 上传测试数据
      在这里插入图片描述
      说明:
      使用linux自带的gzip将testdata(拷贝了bigtable的数据,因为直接gzip bigtable,会删除原始数据)
      或者使用:
      在这里插入图片描述
      说明:
      这样不但可以将原有的文件保留,而且可以将压缩包放到任何目录中,解压缩也一样可以看到bigtable.gz和testdata.gz大小一致

    • 在hdfs根目录创建一个data目录、

    [root@node02 data]# hadoop fs -mkdir /data
    [root@node02 data]# hadoop fs -ls /
    Found 2 items
    drwxr-xr-x   - root supergroup          0 2020-01-04 05:47 /data
    drwxrwxrwx   - root supergroup          0 2019-06-26 06:23 /tmp
    
    • 上传压缩后的数据
      由于数据太小(大约50M),仅有一个block,为了测试,自定义block块为10M:
    hadoop fs -D dfs.blocksize=10485760 -put bigtable.gz /data
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    从上图中明显可以看到:gzip格式的数据,不支持切分的真正含义,并不是说HDFS不会将文件分布式的存储在各个节点,而是在计算的时候,不支持切分,也就是仅仅有一个split,从而也就是仅有一个map,这样的效率是及其低下的。
    (后面还会更详细的讲解)
    正常支持切分的数据,执行流程如下:

    在这里插入图片描述
    而不持支切分的数据,如gzip格式的数据,就只有一个map:
    在这里插入图片描述
    这样直接导致的结果就是:
    一个map任务处理N个HDFS块,而其中大多数块并没有存储在执行该map任务的节点上,执行的效率会非常低

    既然这样,难道压缩数据就没有意义了吗?当然不是,而且在生产环境中数据都是经过压缩处理的,接下来详细讲解HDFS数据的压缩

    详解HDFS文件压缩

    • 文件压缩的两大好处
      (1)减少存储文件所需要的磁盘空间
      (2)加速数据在网络和磁盘上的传输

    • 与Hadoop结合使用的常见压缩方法

    压缩格式工具算法文件扩展名是否可切分
    DEFLATEDEFLATE.deflate
    gzipgzipDEFLATE.gz
    bzip2bzip2bzip2.bz2
    LZOlzopLZO.lzo
    LZ4LZ4.lz4
    SnappySnappy.snappy

    说明:

    1. DEFLATE是一个标准压缩算法,该算法的标准实现是zlib。没有可用于生成DEFLATE文件的常用命令行工具,因为通常都用gzip格式。注意,gzip文件格式只是在DEFLATE格式上增加了文件头和一个文件尾。.deflate扩展名是Hadoop约定的。
    2. 如果LZO文件已经在预处理过程中被索引了,那么LZO文件是可切分的。
    • 详细描述文件的压缩
      所有压缩算法都需要权衡空间/时间:压缩和解压缩速度更快,其代价通常是只能节省少量的空间。上表列出所有压缩工具都提供9个不同选项来控制压缩时必须考虑的权衡:选项-1为优化压缩速度,-9为优化压缩空间。例如,下述命令通过最快压缩方法创建一个名为file.gz的压缩文件:
      gzip -1 file
      不同压缩工具有不同的压缩特性。gzip是一个通用的压缩工具,在空间/时间性能的权衡中,属于其他两个压缩方法之间。bzip2的压缩能力强于gzip(即省空间),但压缩速度更慢一点。尽管gzip的解压速度比要锁速度快,但仍比其他压缩格式要慢一些。另一方面,LZO、LZ4和Snappy均优化压缩速度,其速度比gzip快一个数据量级,但压缩效率稍逊一筹。Snappy和LZ4的解压缩速度比LZO高出很多,通过下面的一张图更形象的看出:压缩比和压缩速度是相反的
      在这里插入图片描述
      上表中的“是否可切分”列表示对应的压缩算法是否支持切分(splitable),也就是说,是否可以搜素数据流的任意位置并进一步往下读取数据。可切分压缩格式尤其适合MapReduce(这个原因上面有讲解,下面进行更详细的描述)

    更详细的描述压缩和输入分片

    在考虑如何压缩将有MapReduce处理的数据时,理解这些压缩格式是否支持切分(splitable)是非常重要的。以一个存储在HDFS文件系统中且压缩前大小为1GB的文件为例。如果HDFS的块大小设置为128MB,那么该文件将被存储在8个块中,把这个文件作为输入数据的MapReduce作业,将创建8个输入分片,其中每个分片作为一个单独的map任务的输入被独立处理。

    现在想象一下,文件是经过gzip压缩的,且压缩后文件大小为1GB。与以前一样,HDFS将这个文件保存为8个数据块。但是,将每个数据块单独作为一个输入分片是无法实现工作的,因为无法实现从gzip压缩数据流的任意位置读取数据,所以让map任务独立与其他任务进行数据读取是行不通的。gzip格式使用DEFLATE算法来存储压缩后的数据,而DEFLATE算法将数据存储在一系列连续的压缩块中。问题在于每个块的起始位置并没有以任何形式标记,所以读取时无法从数据流的任意当前位置前进到下一块的起始位置读取下一个数据块,从而实现与整个数据流的同步。由于上述原因,gzip并不支持文件切分。

    在这种情况下,MapReduce会采用正确的做法,它不会尝试切分gzip压缩文件,因为它知道输入的时gzip压缩文件(通过文件扩展名看出)且gzip不持支切分。这是可行的,但牺牲了数据的本地性:一个map任务处理8个HDFS块,而其中大多数块并没有存储在执行该map任务的节点上。而且,map任务数量越少,作业的粒度就越大,因而运行的时间可能会更长。

    在前面假设的例子中,如果文件时通过LZO压缩的,我们会面临相同的问题,因为这个压缩格式也不支持数据读取和数据流同步。但是,在预处理LZO文件的时候使用包含在Hadoop LZO库文件中的索引工具时可能的,你可以在Google和Github网站上获得该库。该工具构建了切分点索引,如果使用恰当的MapReduce输入格式可有效实现文件的可切分特性。

    另一方面,bzip2文件提供不同数据块之间的同步标识(pi的48位近似值),因而它支持切分。可以参考前面的表,了解每个压缩格式是否支持可切分

    该使用哪种压缩格式

    Hadoop应用处理的数据集非常大,因此需要借助与压缩。使用哪种压缩格式,与待处理的文件的大小、格式和所使用的工具有关。下面有一些建议,大致是按照效率从高到底排列的。

    • 使用容器文件格式,例如顺序文件(Sequence File)、Avro数据文件、ORCFile或者Parquet文件,所有这些文件格式同时支持压缩和切分。通常最好与一个快速压缩工具联合使用,例如,LZO、LZ4或者Snappy
    • 使用支持切分的压缩格式,例如bzip2(尽管bzip2非常慢),或者使用通过索引实现切分的压缩格式,例如LZO
    • 在应用中将文件切分成块,并使用任意一种压缩格式为每个数据块建立压缩文件(不论它是否支持切分)。这种情况下,需要合理选择数据块大小,以确保压缩后的数据块的大小近似于HDFS块的大小
    • 存储未经压缩的文件

    对于大文件来说,不要使用不支持切分整个文件的压缩格式,因为会失去数据的本地性,进而造成MapReduce应用效率低下

    后记

    本文内容参考Hadoop权威指南

    展开全文
  • Java实现zip文件压缩与解压缩--附完整代码

    万次阅读 多人点赞 2019-07-26 14:54:09
    Java实现文件压缩与解压缩-----zip、.7z1. 基本概念1.1 Java中实现zip的压缩与解压缩1.1.1 基本概念1.1.2 zip压缩代码实现1.3 zip压缩代码改进 1. 基本概念 1.1 Java中实现zip的压缩与解压缩 1.1.1 基本概念 ...

    Java中实现zip的压缩与解压缩

    1 基本概念

    1. ZipOutputStream 实现文件的压缩
    • ZipOutputStream (OutputStream out) 创建新的zip输出流
    • void putNextEntry(ZipEntry e) 开始写入新的zip文件条目并将流定位到条目数据的开始处
      条目指的是一个文件夹下的多个文件。
    • ZipEntry(String name) 使用指定名称创建新的zip条目
    1. ZipIutputStream实现文件的解压
    • ZipIutputStream (IutputStream out) 创建新的zip输入流
    • ZipEntry getNextEntry()读取下一个zip条目并将流定位到该条目数据的开始处

    2 zip压缩

    2.1 zip压缩代码实现

    1. 程序完整代码
    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>
    
    1. 运行程序:

    在这里插入图片描述

    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不完美实现

    1. 这个网上有很多代码的,比如:
    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();
            }
        }
    }
    
    展开全文
  • 文件压缩压缩

    千次阅读 2018-09-10 19:12:15
    脑子一热,想到能不能再次压缩文件?没有百度到,想要的答案,自己费事来try try。 看不懂的知识:https://blog.csdn.net/xuchuangqi/article/details/52939705 gzip 对于要压缩的文件,首先使用LZ77算法的一个...
  • 哈夫曼实现文件压缩压缩(c语言)

    万次阅读 多人点赞 2019-01-23 17:04:47
    在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长...
  • 首先,我们将文件压缩这个项目分为五个步骤: 1. 统计字符出现的次数 2. 构建HuffmanTree 3. 生成哈夫曼编码 (Huffman Code) 4. 压缩 (compress) 5. 解压缩 (uncompress) Huffman树 ,又称为最优...
  • linux压缩文件命名

    千次阅读 2014-11-14 14:36:36
    tar是把文件打成一个包,并不压缩; gz是用gzip把打成包的.tar文件压缩; 所以成了一个.tar.gz的文件   压缩 # tar cvfz backup.tar.gz /xxx/  -c, --create  create a new archive  -v, --...
  • java实现对rar文件和zip文件的解压缩

    万次阅读 2017-07-12 16:47:53
    java实现对rar文件和zip文件的解压缩 一.对zip文件的解压缩 1.1 使用ZIP4J实现 zip4j官方说明: ...针对ZIP压缩文件创建、添加、抽出、更新和移除文件 Read/Write password protected Zip files (读写
  • 学习Java压缩zip文件压缩单个文件和多个文件,不包含文件夹;怎样用Java将文件追加到zip文件中。测试类:/** * @FileName:ZipTest.java * @Description: TODO * @Copyright: All rights Reserved, Designed By ...
  • 1 某文件夹下所有文件压缩(不能含文件夹) /**   * 将存放在sourceFilePath目录下的源文件,打包成fileName名称的zip文件,并存放到zipFilePath路径下   * @param sourceFilePath :待压缩文件路径   * @...
  • 本文介绍的方法中会将这些压缩文件在后台一个临时目录 /tmp 中进行解压缩。重启系统后,/tmp 目录的内容将被清空。 在进一步讨论之前,这里先解释一下归档和压缩文件。 归档 是将多个文件或文件夹组合成一个文件的...
  • POI导出多个Excel文件,生成压缩文件

    千次阅读 2018-01-15 10:51:38
    众所周知,每个Excel文件最多可以存储255个sheet。当需要导出的sheet数超过255个,比较好的办法是将多个Excel文件压缩成.zip文件再导出 步骤:1 将需要导出的... 3 将Excel文件生成压缩文件导出 package com.
  • 可以用来压缩打包单文件、多个文件、单个目录、多个目录。 Linux打包命令_tar tar命令可以用来压缩打包单文件、多个文件、单个目录、多个目录。 常用格式: 单个文件压缩打包 tar czvf my.tar.gz file1 多个文件压缩...
  • Linux解、压缩文件及权限命令

    千次阅读 2019-10-15 19:59:58
    tar 解压缩命令中的参数分别代表什么意思? 建立压缩档案 : -c 解压 : -x 查看内容: -t 向压缩归档文件末尾追加文件: -r 更新原压缩包中的文件: -u 必选参数 ...
  • java使用ant实现Zip文件压缩、解压缩Zip文件。 单个文件压缩成Zip文件,多个文件压缩成Zip文件。 使用ant实现大文件压缩
  •  常见的压缩文件扩展名     打包软件tar:将很多文件集结成一个文件  应用度最广的压缩指令gzip  能解开compress、zip和gzip等软件压缩的文件  压缩后的文件为*.gz  (ls -ldSr按文件大小从小到大列出)...
  • 利用哈夫曼树实现文件压缩

    千次阅读 多人点赞 2017-02-27 10:51:49
    3.根据字符的哈夫曼编码进行转换、压缩,然后创建压缩文件。 4.读取压缩文件,读出哈夫曼编码和字符的对照表。解压缩。 数据结构的设计: 1.保存字符次数和字符的数据结构 struct _symbol{ char charac
  •  1、压缩:指通过某些算法,将文件尺寸进行相应的缩小,然而同时又不损失文件的内容。 二、gzip命令(进行压缩与解压)  1、命令作用  可以解开compress、zip与gzip等软件所压缩文件。  2、选项参数  -c:...
  •   程序员在做web等项目的时候,往往都需要添加文件上传、下载、删除的功能,有时是单... 这篇博文主要是讲如何将多个文件压缩并下载下来: 主要有以下几个步骤:1。 首先先遍历出某个文件夹所含有的所有文件im...
  • 哈夫曼树实现文件压缩

    千次阅读 2016-11-05 09:34:40
    最近在学了哈夫曼树之后,作为练习,写了一个文件压缩的小项目; 在这里和大家分享一下;主要实现思路: 利用哈夫曼树的特性对字符进行哈夫曼编码,其中运用到了最小堆;...当解压缩时可以利用配置文件中的内容构造出
  • 哈夫曼树实现文件压缩与解压缩

    万次阅读 多人点赞 2016-06-06 21:23:14
    见识了360压缩的神奇后,想要实现自己的文件压缩程序,然后花了近一个星期的时间去完成文件压缩与解压缩,期间有很多坑,花了很长时间去调试它,最后把坑给填了(真心的感受到了程序员写代码的小小粗心会把自己给...
  • 可以用来压缩打包单文件、多个文件、单个目录、多个目录。 Linux打包命令_tar tar命令可以用来压缩打包单文件、多个文件、单个目录、多个目录。 常用格式: 单个文件压缩打包 tar czvf my.tar.gz file1 多个...
  • WinRAR压缩文件参数详解

    千次阅读 2017-02-10 18:14:14
    将D:/wk.doc 压缩为:final.rar  d:/winrar/rar a d:/final.rar d:/wk.doc  将final.rar中的wk.doc解压到F:盘  rar e d:/final.rar F:  将final.rar转换成自解压文件  rar s final,rar(默认转换到...
  • 解压zip跟rar压缩文件

    千次阅读 2017-04-19 10:49:01
    这里是对zip及rar文件进行解压
  • 一名菜鸟学习编程技术,记录所学...-z:以gzip格式压缩或解压缩文件 -j:以bzip格式压缩或解压缩文件 -t:查看内容 -x:解开档案文件 例: tar -cvf /tmp/etc.tar /etc #将/etc目录下的文件导报到/tmp目录下并命名为e
  • 压缩文件: 排除某些文件

    千次阅读 2019-01-07 17:54:55
    压缩文件: 排除某些文件 在使用tar 的--exclude 命令排除打包的时候,不能加“/”,否则还是会把logs目录以及其下的文件打包进去。 tar -zcvf test.tar.gz --exclude=.svn Core/* tar -zcvf test.tar.gz --exclude...
  • 通常来说,我们查看归档或压缩文件的内容,需要先进行解压缩,然后再查看,比较麻烦。今天给大家介绍 10 不同方法,能够让你轻松地在未解压缩的情况下查看归档或压缩文件的内容。...
  • Linux命令———zip和jar文件压缩解压

    千次阅读 2018-12-28 21:43:26
    (1)ubuntu 使用unzip和zip压缩文件  1.功能作用:解压缩zip文件  2.位置:/usr/bin/unzip  3.格式用法:unzip [-Z] [-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]  4.主要参数  ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 103,444
精华内容 41,377
关键字:

压缩文件时出现tmp文件