澳门新葡萄京官网首页 6

澳门新葡萄京官网首页c#操作Zip压缩文件

本文将介绍Java中利用线程池递归的方式压缩文件夹下面的所有子文件,具体方法如下:

SharpZipLib
文件/文件夹压缩

主线程等待子线程运行结束再完成的效果如何实现
主线程抛出一个子线程异步处理一些东西,这时主线程要等待子线程运行完成再完成(其实我是为了统计运行时间的)。
这里抛出的子线程可能递归的调用自己,就是再抛一个他的子线程出来,但是到底一共抛多少,事先是不知道的。
应用场景:
1)多线程扫描文件夹内的文件,遇到文件夹内有子文件夹,要递归调用扫描线程的,等到全部扫描完成后,返回结果,显示;
澳门新葡萄京官网首页,2)多线程快速排序,第一次肯定是单线程的,第一次排序完成后,会分两半,这两半多线程排,递归调用了这个排序线程,这两半很有可能,极大有可能再各分两半,也就是会有4个子线程的子线程再排序。

Gzip单个文件压缩

对于单个文件使用GZip压缩。

package date0805.demo1;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;

public class GZipRunnable implements Runnable {

    private final File file;

    public GZipRunnable(File file) {
        this.file=file;
    }

    @Override
    public void run() {
        if(!file.getName().endsWith(".gz")) {
            File outputFile=new File(file.getParent(),file.getName()+".gz");
            if(!outputFile.exists()) {
                CountTime countTime = new CountTime(file);
                Thread t=new Thread(countTime);
                t.start();
                try(
                    InputStream in =new BufferedInputStream(new FileInputStream(file));
                    OutputStream out=new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(outputFile)));
                ) {
                    int b;
                    while((b=in.read())!=-1)
                        out.write(b);
                    out.flush();
                } catch(Exception ex) {
                    ex.printStackTrace();
                }
                t.interrupt();
            } else {
                System.out.println(outputFile+"文件已经存在,无法压缩!");
            }
        }
    }
}

一、ZipFile

  ZipFile类用于选择文件或文件夹进行压缩生成压缩包。

  常用属性:

属性 说明
Count 文件数目(注意是在ComitUpdat之后才有)
Password 压缩包密码
Size 压缩包占用空间大小
Name 压缩包名称,默认输出是文件路径
ZipEntry 压缩包里的文件,通过索引[]访问

  其常用方法如下:

方法 说明
Add 添加要进行压缩的文件
AddDirectory 添加文件夹(不会压缩文件夹里的文件)
Delete 删除文件或文件夹
BeginUpdate 开始修改压缩包
CommitUpdate 提交修改
SetComment 添加注释

  示例1(创建压缩文件):

澳门新葡萄京官网首页 1😉

  using (ZipFile zip = ZipFile.Create(@"D:test.zip"))
    {
          zip.BeginUpdate();       zip.SetComment("这是我的压缩包");
          zip.Add(@"D:1.txt");       //添加一个文件
          zip.AddDirectory(@"D:2");  //添加一个文件夹(这个方法不会压缩文件夹里的文件)
          zip.Add(@"D:22.txt");     //添加文件夹里的文件
          zip.CommitUpdate();
     }

澳门新葡萄京官网首页 2😉

  这样生成的压缩包是包含子文件夹,子文件夹也是包含子文件的。

  其中,注释如下:

  澳门新葡萄京官网首页 3

  示例2:修改压缩包

  using (ZipFile zip = new ZipFile(@"D:test.zip"))
      {
          zip.BeginUpdate();
          zip.Add(@"D:2.txt");
          zip.CommitUpdate();
      }

  留意这个示例和上面的有什么不同,上面的是Create方法创建的ZipFile对象,而这里是直接读。因此,如果压缩包里面有文件,则不会改动原来的压缩文件,而是往会里面添加一个。这样就相当于压缩包的修改,而上面是压缩包的创建。

  示例3:读取压缩包里的文件:

澳门新葡萄京官网首页 4😉

  using (ZipFile zip = new ZipFile(@"D:test.zip"))
      {
          foreach (ZipEntry z in zip)
          {
              Console.WriteLine(z);
          }
          ZipEntry z1 = zip[0];
          Console.WriteLine(z1.Name);
     }

澳门新葡萄京官网首页 5😉

我试过网上的那个 CountDownLatch
,但是他只能实现定义好子线程的数量,但是在以上两种情景下,事先你是不知道会有多少个子线程的!

创建线程池进行递归压缩

要实现对一个文件夹下面的所有的子文件进行压缩,首先递归找出所有子文件,然后调用压缩线程进行压缩。

package date0805.demo1;

import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class GZipFiles {

    private final static int THREAD_COUNT=4;
    private static ExecutorService service=Executors.newFixedThreadPool(THREAD_COUNT);
    public static void GZip(File fileArgs) {
        if(!fileArgs.isDirectory()) {
            GZipRunnable gZipRunnable = new GZipRunnable(fileArgs);
            service.submit(gZipRunnable);
        }
        else {
            File[] files = fileArgs.listFiles();
            for(File f:files) {
                GZip(f);
            }
        }
    }
    public static void shutdown() {
        service.shutdown();
    }
}

二、FastZip

  这个类就两个方法:

方法 说明
CreateZip 压缩目录
ExtractZip 解压缩目录

  

  1、FastZip用于快速压缩目录,示例如下:

//快速压缩目录,包括目录下的所有文件
(new FastZip()).CreateZip(@"D:test.zip", @"D:test", true, "");

  这个是递归压缩的。但是局限性就是只能压缩文件夹。

  否则报如下错误:

  澳门新葡萄京官网首页 6

  2、快速解压缩目录

//快速解压
(new FastZip()).ExtractZip(@"D:test.zip", @"D:解压目录", "");

 

c++里有个WaitForSingleObject,java里有么?

压缩提示

package date0805.demo1;

import java.io.File;

public class CountTime implements Runnable {

    private File file;

    public CountTime(File file) {
        super();
        this.file = file;
    }

    @Override
    public void run() {
        System.out.println("正在压缩"+file.getAbsolutePath());
        try {
            while(true) {
                System.out.print(".");
                Thread.sleep(1000);
            }
        }catch (InterruptedException e) {
            System.out.println();
            System.out.println(file.getAbsolutePath()+".gz已经压缩完成!");
        }
    }

}

三、ZipOutputStream与ZipEntry

  • ZipOutputStream:相当于一个压缩包;
  • ZipEntry:相当于压缩包里的一个文件;

  以上两个类是SharpZipLib的主类,最耐玩的就是这两个类。

  ZipOutputStream常用属性:

属性 说明
IsFinished ZipOutputStream是否已结束

  ZipOutputStream常用方法:

方法 说明
CloseEntry 关闭入口,关闭之后不允许再对ZipOutputStream进行操作
Finish 结束写入
GetLevel 读取压缩等级
PutNextEntry 往ZipOutputStream里写入一个ZipEntry
SetComment 压缩包的注释
SetLevel 设置压缩等级,等级越高文件越小
Write 写入文件内容

  使用ZipOutputStream创建一个压缩包并往里面写入一个文件的示例:

澳门新葡萄京官网首页 7😉

        static void Main(string[] args)
        {
            using (ZipOutputStream s = new ZipOutputStream(File.Create(@"D:123.zip")))
            {
                s.SetLevel(6);  //设置压缩等级,等级越高压缩效果越明显,但占用CPU也会更多using (FileStream fs = File.OpenRead(@"D:1.txt"))
                {
                    byte[] buffer = new byte[4 * 1024];  //缓冲区,每次操作大小
                    ZipEntry entry = new ZipEntry(Path.GetFileName(@"改名.txt"));     //创建压缩包内的文件
                    entry.DateTime = DateTime.Now;  //文件创建时间
                    s.PutNextEntry(entry);          //将文件写入压缩包

                    int sourceBytes;
                    do
                    {
                        sourceBytes = fs.Read(buffer, 0, buffer.Length);    //读取文件内容(1次读4M,写4M)
                        s.Write(buffer, 0, sourceBytes);                    //将文件内容写入压缩相应的文件
                    } while (sourceBytes > 0);
                }
                s.CloseEntry();
            }

            Console.ReadKey();
        }

澳门新葡萄京官网首页 8😉

  以上示例仅仅能够压缩文件,要压缩文件夹就要使用递归的方式,循环子目录并压缩子目录里的文件。

  示例2:文件夹压缩,保持原文件夹架构:

澳门新葡萄京官网首页 9😉

    class Program
    {
        static void Main(string[] args)
        {
            string Source = @"D:test";
            string TartgetFile = @"D:test.zip";
            Directory.CreateDirectory(Path.GetDirectoryName(TartgetFile));
            using (ZipOutputStream s = new ZipOutputStream(File.Create(TartgetFile)))
            {
                s.SetLevel(6);
                Compress(Source, s);
                s.Finish();
                s.Close();
            }

            Console.ReadKey();
        }

        /// <summary>
        /// 压缩
        /// </summary>
        /// <param name="source">源目录</param>
        /// <param name="s">ZipOutputStream对象</param>
        public static void Compress(string source, ZipOutputStream s)
        {
            string[] filenames = Directory.GetFileSystemEntries(source);
            foreach (string file in filenames)
            {
                if (Directory.Exists(file))
                {
                    Compress(file, s);  //递归压缩子文件夹
                }
                else
                {
                    using (FileStream fs = File.OpenRead(file))
                    {
                        byte[] buffer = new byte[4 * 1024];
                        ZipEntry entry = new ZipEntry(file.Replace(Path.GetPathRoot(file),""));     //此处去掉盘符,如D:1231.txt 去掉D:
                        entry.DateTime = DateTime.Now;
                        s.PutNextEntry(entry);

                        int sourceBytes;
                        do
                        {
                            sourceBytes = fs.Read(buffer, 0, buffer.Length);
                            s.Write(buffer, 0, sourceBytes);
                        } while (sourceBytes > 0);
                    }
                }
            }
        }
    }

澳门新葡萄京官网首页 10😉

  附上解压缩方法:

澳门新葡萄京官网首页 11😉

        /// <summary>
        /// 解压缩
        /// </summary>
        /// <param name="sourceFile">源文件</param>
        /// <param name="targetPath">目标路经</param>
        public bool Decompress(string sourceFile, string targetPath)
        {
            if (!File.Exists(sourceFile))
            {
                throw new FileNotFoundException(string.Format("未能找到文件 '{0}' ", sourceFile));
            }
            if (!Directory.Exists(targetPath))
            {
                Directory.CreateDirectory(targetPath); 
            }
            using (ZipInputStream s = new ZipInputStream(File.OpenRead(sourceFile)))
            {
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    string directorName = Path.Combine(targetPath, Path.GetDirectoryName(theEntry.Name));
                    string fileName = Path.Combine(directorName, Path.GetFileName(theEntry.Name));
                    // 创建目录
                    if (directorName.Length > 0)
                    {
                        Directory.CreateDirectory(directorName);
                    }
                    if (fileName != string.Empty)
                    {
                        using (FileStream streamWriter = File.Create(fileName))
                        {
                            int size = 4096;
                            byte[] data = new byte[ 4 * 1024];
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else break;
                            }
                        }
                    }
                }
            }
            return true;
        }

澳门新葡萄京官网首页 12😉

  ZipEntry就没什么好说的了,都是一些属性,指示一下,实际用到的很少。

转自:

测试代码

package date0805.demo1;

import java.io.File;

public class Test {

    public static void main(String[] args) {
        File file=new File("D://新建文件夹");
        GZipFiles.GZip(file);
        GZipFiles.shutdown();
    }
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注