C#實現文件Zip壓縮


原文地址:https://blog.csdn.net/xinxin_2011/article/details/100535917?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-7-100535917.pc_agg_new_rank&utm_term=c%23+%E5%8E%8B%E7%BC%A9%E5%A4%A7%E6%96%87%E4%BB%B6&spm=1000.2123.3001.4430

 

可適用於大文件壓縮

壓縮大文件時緩存buffer創建的時候出現溢出。那么這個緩存創建了多大呢?fs.Length!!沒錯,文件多大咱就創建多大,這樣相當於把整個文件放入內存
解決思路是開辟一個固定大小的緩存區,循環讀取文件進行壓縮,但是這里有個問題,壓縮時是先寫入ZipEntry再寫入文件數據的,而ZipEntry里面包含了crc信息,不把文件讀完,就計算不出來crc。這里采用讀取兩遍文件的策略,第一遍計算crc,第二遍再寫入文件數據。
修改之后,foreach循環里的代碼如下,直接上代碼

        /// <summary>
        /// 壓縮大文件
        /// </summary>
        /// <param name="args"></param>
        /// <param name="password"></param>
        public static void ZipFileMainBest(string[] args, string password)
        {

            List<string> files = new List<string>();
            string[] filetypes;
            if (ConfigurationManager.AppSettings["FileType"].ToString() != "")
            {
                filetypes = ConfigurationManager.AppSettings["FileType"].ToString().Split(';');
                Director(args[0], filetypes, files);
            }
            else
            {
                Director(args[0], files);
            }

            int count = files.Count;
            string[] ff = new string[count];

            int i = 0;
            foreach (var item in files)
            {
                ff[i] = item.ToString();
                i++;
            }

            string[] filenames = ff; //Directory.GetFiles(args[0]);
            if (filenames.Length > 0)
            {
                ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));

                s.SetLevel(6); // 0 - store only to 9 - means best compression 

                s.Password = md5.encrypt(password);
                s.Password = password; //md5.encrypt(password);
                Crc32 crc = new Crc32();
                foreach (string file in filenames)
                {
                    int readlen = 4096000;
                    FileStream fs = File.OpenRead(file);
                    byte[] buffer = new byte[4096000];       // 每次4M
                    Array arr = file.Split('\\');
                    string le = arr.GetValue(arr.Length - 1).ToString();
                    ZipEntry entry = new ZipEntry(le);
                    entry.DateTime = DateTime.Now;
                    entry.Size = fs.Length;

                    long remaindSize = fs.Length;
                    // 計算crc
                    crc.Reset();
                    while (remaindSize > 0)
                    {
                        if (remaindSize < readlen)
                            readlen = (int)remaindSize;

                        fs.Read(buffer, 0, readlen);
                        remaindSize -= readlen;

                        crc.Update(buffer, 0, readlen);
                    }
                    entry.Crc = crc.Value;
                    s.PutNextEntry(entry);

                    // 壓縮數據
                    readlen = 4096000;
                    remaindSize = fs.Length;
                    fs.Seek(0, SeekOrigin.Begin);
                    while (remaindSize > 0)
                    {
                        if (remaindSize < readlen)
                            readlen = (int)remaindSize;

                        fs.Read(buffer, 0, readlen);
                        remaindSize -= readlen;
                        s.Write(buffer, 0, readlen);
                    }
                    s.Flush();
                    fs.Close();
                }

                s.Finish();
                s.Close();
            }
        }

 

核心代碼

if (filenames.Length > 0)
            {
                ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));

                s.SetLevel(6); // 0 - store only to 9 - means best compression 

                s.Password = md5.encrypt(password);
                s.Password = password; //md5.encrypt(password);
                Crc32 crc = new Crc32();
                foreach (string file in filenames)
                {
                    int readlen = 4096000;
                    FileStream fs = File.OpenRead(file);
                    byte[] buffer = new byte[4096000];       // 每次4M
                    Array arr = file.Split('\\');
                    string le = arr.GetValue(arr.Length - 1).ToString();
                    ZipEntry entry = new ZipEntry(le);
                    entry.DateTime = DateTime.Now;
                    entry.Size = fs.Length;

                    long remaindSize = fs.Length;
                    // 計算crc  ,不計算也可行
                    crc.Reset();
                    while (remaindSize > 0)
                    {
                        if (remaindSize < readlen)
                            readlen = (int)remaindSize;

                        fs.Read(buffer, 0, readlen);
                        remaindSize -= readlen;

                        crc.Update(buffer, 0, readlen);
                    }
                    entry.Crc = crc.Value;
                    s.PutNextEntry(entry);

                    // 壓縮數據
                    readlen = 4096000;
                    remaindSize = fs.Length;
                    fs.Seek(0, SeekOrigin.Begin);
                    while (remaindSize > 0)
                    {
                        if (remaindSize < readlen)
                            readlen = (int)remaindSize;

                        fs.Read(buffer, 0, readlen);//fs 是循序讀取文件流
                        remaindSize -= readlen;
                        s.Write(buffer, 0, readlen);
                    }
                    s.Flush();
                    fs.Close();
                }

                s.Finish();
                s.Close();
            }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM