Giải nén tập tin theo chương trình trong .net


221

Tôi đang cố gắng giải nén theo chương trình một tệp nén.

Tôi đã thử sử dụng System.IO.Compression.GZipStreamlớp trong .NET, nhưng khi ứng dụng của tôi chạy (thực sự là một bài kiểm tra đơn vị) tôi nhận được ngoại lệ này:

System.IO.InvalidDataException: Số ma thuật trong tiêu đề GZip là không chính xác. Hãy chắc chắn rằng bạn đang truyền trong luồng GZip ..

Bây giờ tôi nhận ra rằng một .ziptệp không giống như một .gztệp và nó GZipkhông giống với Zip.

Tuy nhiên, vì tôi có thể trích xuất tệp bằng cách nhấp đúp vào tệp được nén bằng tay và sau đó nhấp vào nút "Trích xuất tất cả tệp", tôi nghĩ rằng cũng nên có cách thực hiện mã đó.

Do đó, tôi đã cố gắng sử dụng Process.Start()với đường dẫn đến tệp nén là đầu vào. Điều này khiến ứng dụng của tôi mở Cửa sổ hiển thị nội dung trong tệp được nén. Điều đó không sao, nhưng ứng dụng sẽ được cài đặt trên một máy chủ không có ai xung quanh để nhấp vào nút "Trích xuất tất cả các tệp".

Vì vậy, làm cách nào để ứng dụng của tôi giải nén các tệp trong các tệp nén?

Hoặc có một cách khác để làm điều đó? Tôi thích làm điều đó bằng mã, mà không cần tải xuống bất kỳ thư viện hoặc ứng dụng của bên thứ ba nào; bộ phận an ninh không quá thích điều đó ...


12
Bộ phận bảo mật của bạn hạnh phúc hơn khi bạn viết mã của riêng mình cho một cái gì đó hơn là sử dụng một thư viện đã được gỡ lỗi và nhìn bằng nhiều mắt? Bạn có thể sử dụng thư viện VÀ "thực hiện theo mã" (lấy nguồn và tự biên dịch nó) nhưng tôi thấy việc phát minh lại bánh xe là một vấn đề lớn hơn bất kỳ vấn đề bảo mật nào do sử dụng thư viện đã thử và đúng.
Jared Updike

10
@Jared - Khi quản lý có ý tưởng trong đầu ...
Steven Evers

4
Có ít rủi ro hơn cho bộ phận bảo mật nếu bạn nhận được sản phẩm của bên thứ ba. Chỉ cần tải xuống dotnetzip và đổi tên nó "[chèn tên công ty] .zipl Library.dll"
Simon

Câu trả lời:


59

Chúng tôi đã sử dụng SharpZipLib thành công trên nhiều dự án. Tôi biết đó là một công cụ của bên thứ ba, nhưng mã nguồn được bao gồm và có thể cung cấp một số thông tin chi tiết nếu bạn chọn phát minh lại bánh xe ở đây.


3
Tôi đã thử sử dụng SharpZipLib và nó hoạt động tốt. Tôi đoán tôi sẽ phải xem liệu việc cấm đối với libs và apss của bên thứ ba là một quy tắc nghiêm ngặt hay hơn là một hướng dẫn.
Petteri

10
Tôi không biết về công ty của bạn, nhưng kinh nghiệm của tôi luôn là có thể có ngoại lệ đối với loại quy tắc đó nếu bạn viết mô tả trường hợp kinh doanh về lý do tại sao bạn muốn ngoại lệ. Chỉ ra các khoản tiết kiệm chi phí v. DIY, cũng như thực tế là nguồn có thể được kiểm tra. Là một dự phòng, bạn thường có thể được phép sử dụng nguồn ngay cả khi họ sẽ không cho phép bạn sử dụng dll - sau đó chỉ cần tự biên dịch nó (hoặc ít nhất là các phần bạn thực sự cần sử dụng ...).
RolandTumble

Bạn không phải sử dụng các thư viện bên ngoài để giải nén các tệp zip, bạn có thể sử dụng Shell32 từ System32. Vui lòng xem stackoverflow.com/a/43066281/948694
arturn 28/03/2017

490

Với .NET 4.5 bây giờ bạn có thể giải nén các tệp bằng .NET framework:

using System;
using System.IO;

namespace ConsoleApplication
{
  class Program
  {
    static void Main(string[] args)
    {
      string startPath = @"c:\example\start";
      string zipPath = @"c:\example\result.zip";
      string extractPath = @"c:\example\extract";

      System.IO.Compression.ZipFile.CreateFromDirectory(startPath, zipPath);
      System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, extractPath);
    }
  }
}

Đoạn mã trên được lấy trực tiếp từ tài liệu của Microsoft: http://msdn.microsoft.com/en-us/l Library / ms404280 (v = vs.110) .aspx

ZipFileđược chứa trong lắp ráp System.IO.Compression.FileSystem. (Cảm ơn nateirvin ... xem bình luận bên dưới)


118
BTW, ZipFileđược chứa trong lắp ráp System.IO.Compression.FileSystem.
nateirvin

73
Điều đó có nghĩa là bạn cần thêm một tham chiếu DLL vào cụm khung System.IO.Compression.FileSystem.dll.
Chris Schiffhauer

những gì về tập tin .rar. mã trên không thể giải nén tập tin .rar.
Raghu

1
Tôi đã thử điều này trong api web lõi asp.net của tôi, nó đọc mục đầu tiên tốt, nhưng trong lần nhập thứ hai, nó luôn báo lỗi A local file header is corrupt. Bất kỳ về điều này?
SoftSan

Tương tự với @SoftSan. Tôi cũng nhận được lỗi đó. Phải làm sao?
Giàu

101

Dành cho .Net 4.5+

Không phải lúc nào cũng muốn ghi tệp không nén vào đĩa. Là một nhà phát triển ASP.Net, tôi sẽ phải sử dụng các quyền để cấp quyền cho ứng dụng của mình để ghi vào hệ thống tập tin. Bằng cách làm việc với các luồng trong bộ nhớ, tôi có thể bỏ qua tất cả những điều đó và đọc các tệp trực tiếp:

using (ZipArchive archive = new ZipArchive(postedZipStream))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
         var stream = entry.Open();
         //Do awesome stream stuff!!
    }
}

Ngoài ra, bạn vẫn có thể ghi tệp giải nén ra đĩa bằng cách gọi ExtractToFile():

using (ZipArchive archive = ZipFile.OpenRead(pathToZip))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        entry.ExtractToFile(Path.Combine(destination, entry.FullName));
    }
} 

Để sử dụng ZipArchivelớp, bạn sẽ cần thêm một tham chiếu đến System.IO.Compressionkhông gian tên và đến System.IO.Compression.FileSystem.


8
Có thực sự mất MSFT cho đến 4,5+ để thêm bộ giải nén gốc không?
John Peters

2
@JohnPeter GZipStream đã được thêm lại vào .Net 2.0 ( msdn.microsoft.com/en-us/l Library / trộm ). Tuy nhiên, nó không giúp bạn dễ dàng làm việc với nhiều tệp trong kho lưu trữ trong bộ nhớ. Các ZipArchiveđối tượng mới phù hợp với hóa đơn độc đáo.
Ông sử thi

1
Đây là một giải pháp thay thế đặc biệt tốt vì nó cho phép giải nén mà không cần sử dụng hệ thống tệp (trong trường hợp của tôi, tôi đang làm việc với các tài nguyên nhúng) và nó cũng không phải là tiện ích mở rộng của bên thứ ba.
ANeves

1
Tại sao tôi nên sử dụng một foreachvòng lặp để ExtractToFilekhi tôi chỉ có thể sử dụng ZipFile.ExtractToDirectory(inputFile, outputDir);Ưu điểm của phương thức đầu tiên là gì?
Robot Fluffy

1
trong .NET 4.6.1 tôi không thể lấy 'ZipArchive' từ 'System.IO.Compression.FileSystem', có ý tưởng nào không?
Ravi Anand

55

Miễn phí và không có tệp DLL bên ngoài. Tất cả mọi thứ là trong một tập tin CS. Một lần tải xuống chỉ là tệp CS, một lần tải xuống khác là một ví dụ rất dễ hiểu. Chỉ cần thử nó ngày hôm nay và tôi không thể tin được việc thiết lập đơn giản như thế nào. Nó làm việc trên lần thử đầu tiên, không có lỗi, không có gì.

https://github.com/jaime-olivares/zipstorer


Nói quá sớm! Tôi muốn làm tăng các tệp từ luồng tải xuống http ngay lập tức. Điều này không hoạt động vì nó đang sử dụng các hoạt động Tìm kiếm trên luồng :( Vâng, nhờ mã nguồn mà tôi có thể viết ZipStream của riêng mình ngay bây giờ ...
oyophant

giải pháp tốt nhất cho vấn đề của tôi, vì tôi đang viết một ứng dụng cập nhật và tôi không thể liên quan đến bất kỳ DLL nào trong quá trình trích xuất kể từ đó tôi cũng sẽ phải cập nhật chúng .... điều này thật tốt. Cảm ơn bạn!
Niklas

27

Sử dụng thư viện DotNetZip tại http://www.codeplex.com/DotNetZip

thư viện lớp và bộ công cụ để thao tác các tệp zip. Sử dụng VB, C # hoặc bất kỳ ngôn ngữ .NET nào để dễ dàng tạo, trích xuất hoặc cập nhật tệp zip ...

DotNetZip hoạt động trên PC với .NET Framework đầy đủ và cũng chạy trên các thiết bị di động sử dụng .NET Compact Framework. Tạo và đọc các tệp zip trong VB, C # hoặc bất kỳ ngôn ngữ .NET hoặc bất kỳ môi trường tập lệnh nào ...

Nếu tất cả những gì bạn muốn là một lớp DeflateStream hoặc GZipStream tốt hơn để thay thế lớp được tích hợp sẵn trong .NET BCL, DotNetZip cũng có điều đó. DeflateStream và GZipStream của DotNetZip có sẵn trong một hội đồng độc lập, dựa trên cổng .NET của Zlib. Các luồng này hỗ trợ các mức nén và cung cấp hiệu suất tốt hơn nhiều so với các lớp tích hợp. Ngoài ra còn có ZlibStream để hoàn thành bộ (RFC 1950, 1951, 1952) ...


1
Hmmm ... Nhưng đó là một thư viện của bên thứ ba!
Petteri

30
Làm thế nào rất quan sát của bạn. Trừ khi bạn cảm thấy muốn dành vài tháng để thực hiện trình đọc tệp Zip của riêng mình, đây là lựa chọn tốt nhất của bạn.
Sam Axe

Đây là cách tốt hơn so với SharpZipLib
Kugel

5
Bạn đang hỏi tôi câu hỏi về một câu trả lời gần 5 tuổi. Làm một vài nghiên cứu. Tôi chắc chắn bạn sẽ tìm thấy một câu trả lời.
Sam Axe

2
@PhilCooper Đây là một câu hỏi rất cũ tôi khuyên bạn nên sử dụng System.IO.Compression.ZipFile tích hợp. IIRC Tôi đã có những trải nghiệm thực sự tồi tệ với SharpZipLib trong quá khứ dựa trên kinh nghiệm của tôi về việc tạo ra hàng ngàn khóa kéo khi đang bay.
Kugel

9
String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

Để sử dụng lớp ZipFile, bạn phải thêm một tham chiếu đến cụm System.IO.Compression.FileSystem trong dự án của bạn



2

Các tệp zip tiêu chuẩn thường sử dụng thuật toán khử.

Để giải nén các tập tin mà không cần sử dụng các thư viện của bên thứ ba, hãy sử dụng DeflateStream. Bạn sẽ cần thêm một chút thông tin về định dạng lưu trữ tệp zip vì Microsoft chỉ cung cấp thuật toán nén.

Bạn cũng có thể thử sử dụng zipfldr.dll. Đây là thư viện nén của Microsoft (thư mục nén từ menu Gửi đến). Nó dường như là một thư viện com nhưng nó không có giấy tờ. Bạn có thể có thể làm cho nó hoạt động cho bạn thông qua thử nghiệm.


Tôi đang thử lớp DeflateStream. Lần này tôi nhận được System.IO.InvalidDataException: Chiều dài khối không khớp với phần bù của nó ..
Petteri

Như tôi đã nói ở trên, Microsoft chỉ cung cấp thuật toán. Bạn cũng sẽ cần thông tin về định dạng lưu trữ zip. vi.wikipedia.org/wiki/ZIP_(file_format) sẽ giúp bạn bắt đầu. Xem các tài liệu tham khảo ở dưới cùng của trang để biết các liên kết đến thông tin chi tiết hơn.
Kenneth Cochran

2
Tôi cũng tình cờ gặp System.IO.Packaging.Package trong .NET 3.5. Có vẻ như nó có thể thực hiện các mẹo mặc dù nó không trực quan lắm.
Kenneth Cochran

2

Tôi sử dụng điều này để nén hoặc giải nén nhiều tập tin. Công cụ Regex không bắt buộc, nhưng tôi sử dụng nó để thay đổi dấu ngày và loại bỏ dấu gạch dưới không mong muốn. Tôi sử dụng chuỗi rỗng trong chuỗi Nén >> zipPath để thêm tiền tố vào tất cả các tệp nếu cần. Ngoài ra, tôi thường nhận xét hoặc Nén () hoặc Giải nén () dựa trên những gì tôi đang làm.

using System;
using System.IO.Compression;
using System.IO;
using System.Text.RegularExpressions;

namespace ZipAndUnzip
{
    class Program
    {
        static void Main(string[] args)
        {
            var directoryPath = new DirectoryInfo(@"C:\your_path\");

            Compress(directoryPath);
            Decompress(directoryPath);
        }

        public static void Compress(DirectoryInfo directoryPath)
        {
            foreach (DirectoryInfo directory in directoryPath.GetDirectories())
            {
                var path = directoryPath.FullName;
                var newArchiveName = Regex.Replace(directory.Name, "[0-9]{8}", "20130913");
                newArchiveName = Regex.Replace(newArchiveName, "[_]+", "_");
                string startPath = path + directory.Name;
                string zipPath = path + "" + newArchiveName + ".zip";

                ZipFile.CreateFromDirectory(startPath, zipPath);
            }

        }

        public static void Decompress(DirectoryInfo directoryPath)
        {
            foreach (FileInfo file in directoryPath.GetFiles())
            {
                var path = directoryPath.FullName;
                string zipPath = path + file.Name;
                string extractPath = Regex.Replace(path + file.Name, ".zip", "");

                ZipFile.ExtractToDirectory(zipPath, extractPath);
            }
        }


    }
}

Điều này yêu cầu dot net 4.5 - chỉ là một ghi chú như những người khác đã trả lời với ZipFile lưu ý và tôi vẫn đang sử dụng 3.5.
Thronk

2

Điều này sẽ làm điều đó System.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)


1

Từ đây :

Các đối tượng GZipStream được nén vào một tệp có phần mở rộng .gz có thể được giải nén bằng nhiều công cụ nén phổ biến; tuy nhiên, lớp này vốn không cung cấp chức năng để thêm tệp vào hoặc trích xuất tệp từ kho lưu trữ .zip.


1

Bạn có thể làm tất cả trong .NET 3.5 bằng cách sử dụng DeflateStream. Điều còn thiếu trong .NET 3.5 là khả năng xử lý các phần tiêu đề tệp được sử dụng để sắp xếp các tệp nén. PKWare đã xuất bản thông tin này, bạn có thể sử dụng để xử lý tệp zip sau khi bạn tạo các cấu trúc được sử dụng. Nó không đặc biệt khó chịu, và đó là một cách thực hành tốt trong việc xây dựng công cụ mà không cần sử dụng mã của bên thứ 3.

Đó không phải là câu trả lời một dòng, nhưng hoàn toàn có thể thực hiện được nếu bạn sẵn sàng và có thể tự mình dành thời gian. Tôi đã viết một lớp để làm điều này trong một vài giờ và những gì tôi nhận được từ đó là khả năng nén và giải nén các tệp chỉ bằng .NET 3.5.


0

Tôi đã phát hiện ra cái này (gói Unzip trên NuGet) ngày hôm nay, vì tôi gặp phải một lỗi cứng trong DotNetZip và tôi nhận ra rằng thực sự đã có rất nhiều công việc được thực hiện trên DotNetZip trong hai năm qua.

Gói Unzip gọn gàng và nó đã thực hiện công việc cho tôi - nó không có lỗi mà DotNetZip mắc phải. Ngoài ra, đó là một tệp nhỏ hợp lý, dựa trên Microsoft BCL để giải nén thực tế. Tôi có thể dễ dàng thực hiện các điều chỉnh mà tôi cần (để có thể theo dõi tiến trình trong khi giải nén). Tôi khuyến khích điều đó.


0

Từ các nguồn nhúng:

using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.zip"))
{
    using (ZipArchive zip = new ZipArchive(_pluginZipResourceStream))
    {
        zip.ExtractToDirectory(Application.StartupPath);
    }
}

0

Cho đến bây giờ, tôi đã sử dụng các quy trình cmd để trích xuất một tệp .iso, sao chép nó vào một đường dẫn tạm thời từ máy chủ và trích xuất trên thanh usb. Gần đây tôi đã thấy rằng điều này đang hoạt động hoàn hảo với .iso nhỏ hơn 10Gb. Đối với một iso như 29Gb, phương thức này bị kẹt bằng cách nào đó.

    public void ExtractArchive()
    {
        try
        {

            try
            {
                Directory.Delete(copyISOLocation.OutputPath, true); 
            }
            catch (Exception e) when (e is IOException || e is UnauthorizedAccessException)
            {
            }

            Process cmd = new Process();
            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;
            cmd.StartInfo.CreateNoWindow = true;
            cmd.StartInfo.UseShellExecute = false;
            cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

            //stackoverflow
            cmd.StartInfo.Arguments = "-R";

            cmd.Disposed += (sender, args) => {
                Console.WriteLine("CMD Process disposed");
            };
            cmd.Exited += (sender, args) => {
                Console.WriteLine("CMD Process exited");
            };
            cmd.ErrorDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process error data received");
                Console.WriteLine(args.Data);
            };
            cmd.OutputDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process Output data received");
                Console.WriteLine(args.Data);
            };

            //stackoverflow


            cmd.Start();

            cmd.StandardInput.WriteLine("C:");
            //Console.WriteLine(cmd.StandardOutput.Read());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine("cd C:\\\"Program Files (x86)\"\\7-Zip\\");
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine(string.Format("7z.exe x -o{0} {1}", copyISOLocation.OutputPath, copyISOLocation.TempIsoPath));
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();
            cmd.StandardInput.Close();
            cmd.WaitForExit();
            Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            Console.WriteLine(cmd.StandardError.ReadToEnd());

0

bạn có thể sử dụng mã dòng lệnh Info-unzip. Bạn chỉ cần tải xuống unzip.exe từ trang web chính thức của Info-unzip.

 internal static void Unzip(string sorcefile)
    {
        try
        {
            AFolderFiles.AFolderFilesDelete.DeleteFolder(TempBackupFolder); // delete old folder   
            AFolderFiles.AFolderFilesCreate.CreateIfNotExist(TempBackupFolder); // delete old folder   
           //need to Command command also to export attributes to a excel file
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; // window type
            startInfo.FileName = UnzipExe;
            startInfo.Arguments = sorcefile + " -d " + TempBackupFolder;
            process.StartInfo = startInfo;
            process.Start();
            //string result = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
            process.Dispose();
            process.Close();
        }
        catch (Exception ex){ throw ex; }
    }        
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.