Breaking News
Loading...
Thursday, July 18, 2013

Tạo và giải nén file Zip với C#

7/18/2013 05:29:00 PM
Việc nén dữ liệu vào một file zip là rất cân thiết, với những mục đích khác nhau. Như nén file lại để gửi cho người khác qua email. Hoặc với mục đích bảo mật đặt password cho file zip đó. Trong C# ta có thể dễ dàng nén thành 1 file zip và giải nén file này.
Trong phần này sẽ giới thiệu thư viện DLL ICSharpCode.SharpZipLib. Đây là thư viện được tạo ra giúp chúng ta dễ dàng thao tác với tạo và giải nén file zip. Thư viện này đã có trong thư mục mã nguồn ở cuối trang.
Ví dụ: Ta có 1 folder tên là “Tep” ở cùng thư mục chương trình, và 1 file zip có tên là gianen.zip với password là “12345”, viết chương trình có 2 nút lệnh, 1 nút là nén folder “Tep” thành file zip với tên là danen.zip và password là “6789” lưu vào ổ D, 1 nút là giải nén file zip giainen.zip lưu vào ổ D.
Code:
Ta tạo 1 ứng dụng WindowsForm với 2 nút Button là “Nén file” và “Giải nén file”. Và ta Add Reference thư viện ICSharpCode.SharpZipLib.dll vào trong Project vừa tạo (Add bằng cách ở thanh menu chọn Project -> Add Reference -> Chuyển sang tab Browse và tìm đến thư viện đó).
Sau khi Add thư viện xong ta tiến hành viết code. Ta có 2 hàm quan trọng là CreateSample(tạo file zip) và ExtractZipFile(giải nén).

Lưu ý: Bạn tạo form có 2 nút "Nén" và Giải Nén" rồi cứ việc gọi các hàm tương ứng bên dưới là sẽ hoàn chỉnh chương trình

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
//Khai báo sử dụng thư viện ICSharpCode.SharpZipLib.dll
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Core;

namespace Zipfile
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        #region///Hàm tạo file nén create zip có pass
        public void CreateSample(string outPathname, string password, string folderName)
        //outPathname: tên và đường dẫn lưu kết quả (ví dụ tên là ketqua.zip lưu ổ E, "E:\\ketqua.zip")
        //password: là password thiết lập cho file zip (ví dụ pass là "12345")
        //folderName: là đường dẫn folder dữ liệu (ví dụ có folder "data" ở ổ C, "C:\\data")
        //CreateSample("C:\\ketqua.zip", "12345", "C:\\data");
        //Chú ý nếu ketqua.zip đã tồn tại trong ổ E thì cần phải xóa bỏ file này thì mới tạo được
        {

            FileStream fsOut = File.Create(outPathname);
            ZipOutputStream zipStream = new ZipOutputStream(fsOut);

            zipStream.SetLevel(3); //0-9,có 9 mức nén, mức 9 là cao nhất

            zipStream.Password = password;

            int folderOffset = folderName.Length + (folderName.EndsWith("\\") ? 0 : 1);

            CompressFolder(folderName, zipStream, folderOffset);

            zipStream.IsStreamOwner = true;
            zipStream.Close();
        }
       
        private void CompressFolder(string path, ZipOutputStream zipStream, int folderOffset)
        {

            string[] files = Directory.GetFiles(path);

            foreach (string filename in files)
            {

                FileInfo fi = new FileInfo(filename);

                string entryName = filename.Substring(folderOffset);
                entryName = ZipEntry.CleanName(entryName);
                ZipEntry newEntry = new ZipEntry(entryName);
                newEntry.DateTime = fi.LastWriteTime;

                newEntry.Size = fi.Length;

                zipStream.PutNextEntry(newEntry);

                byte[] buffer = new byte[4096];
                using (FileStream streamReader = File.OpenRead(filename))
                {
                    StreamUtils.Copy(streamReader, zipStream, buffer);
                }
                zipStream.CloseEntry();
            }
            string[] folders = Directory.GetDirectories(path);
            foreach (string folder in folders)
            {
                CompressFolder(folder, zipStream, folderOffset);
            }
        }
        #endregion
        #region///Hàm giải nén file zip có password
        public void ExtractZipFile(string archiveFilenameIn, string password, string outFolder)
        //archiveFilenameIn: đường dẫn file zip (ví dụ trong ổ E có file zip là ketqua.zip, "E:\\ketqua.zip")
        //password: là password đã đặt cho file zip như ví dụ trên là ketqua.zip(ví dụ "12345678")
        //outFolder: đường dẫn folder lưu kết quả giải nén (ví dụ trong ổ C có thư mục là data, "C:\\data")
        //ExtractZipFile("E:\\ketqua.zip","12345678","C:\\data")
        {
            ZipFile zf = null;
            try
            {
                FileStream fs = File.OpenRead(archiveFilenameIn);
                zf = new ZipFile(fs);
                if (!String.IsNullOrEmpty(password))
                {
                    zf.Password = password;
                }
                foreach (ZipEntry zipEntry in zf)
                {
                    if (!zipEntry.IsFile)
                    {
                        continue;
                    }
                    String entryFileName = zipEntry.Name;

                    byte[] buffer = new byte[4096];
                    Stream zipStream = zf.GetInputStream(zipEntry);

                    String fullZipToPath = Path.Combine(outFolder, entryFileName);
                    string directoryName = Path.GetDirectoryName(fullZipToPath);
                    if (directoryName.Length > 0)
                        Directory.CreateDirectory(directoryName);

                    if (System.IO.File.Exists(fullZipToPath) != true)
                    {
                        using (FileStream streamWriter = File.Create(fullZipToPath))
                        {
                            StreamUtils.Copy(zipStream, streamWriter, buffer);
                        }
                    }
                    else
                    {
                        using (FileStream streamWriter = new FileStream(fullZipToPath, FileMode.Append))
                        {
                            StreamUtils.Copy(zipStream, streamWriter, buffer);
                        }
                    }
                }
            }
            finally
            {
                if (zf != null)
                {
                    zf.IsStreamOwner = true;
                    zf.Close();
                }
            }
        }
        #endregion
        //Button Nén file thành file Zip
        private void button2_Click(object sender, EventArgs e)
        {
            //Lấy đường dẫn file Tep.txt để cùng với thư mục chương trình
            string folderName = Path.GetDirectoryName(Application.ExecutablePath) + "\\Tep";
            //MessageBox.Show(folderName);
            CreateSample("E:\\danen.zip""12345", folderName);
            MessageBox.Show("Đã nén thành công""Thông báo");
        }
        //Button Giải nén
        private void button3_Click(object sender, EventArgs e)
        {
            ExtractZipFile(Path.GetDirectoryName(Application.ExecutablePath) + "\\giainen.zip""6789","E:\\giainen");
            MessageBox.Show("Đã giải nén thành công""Thông báo");
        }
    }

}

5 comments:

  1. Cho em hỏi hàm CompressFolde trong CreateSample báo chưa được khởi tạo thì sao ạ, trong bài viết chưa có share DLL

    ReplyDelete
    Replies
    1. DLL đó là ICSharpCode.SharpZipLib.dll đó bạn. Nếu bạn tìm không có thì có thể dowload DLl tại link: https://code.google.com/p/mepg/downloads/detail?name=ICSharpCode.SharpZipLib.dll&can=2&q=

      Delete
  2. Sao tại hàm: CompressFolder()
    Nó báo tại dòng : using (FileStream streamReader = File.OpenRead(filename)) là:
    The process cannot access the file 'E:\SQLBACKUPS\20161409201692607.rar' because it is being used by another process.

    ReplyDelete
    Replies
    1. Mình đã thử ra ngoài nén bằng tay bình thường thì vẫn đc( nghĩa là không có ai can thiệp vào file đó nữa)

      Delete
  3. This comment has been removed by the author.

    ReplyDelete

 
Toggle Footer