Buka zip file secara terprogram dalam .net

221

Saya mencoba secara unzip membuka file zip.

Saya telah mencoba menggunakan System.IO.Compression.GZipStreamkelas di .NET, tetapi ketika aplikasi saya berjalan (sebenarnya tes unit) saya mendapatkan pengecualian ini:

System.IO.InvalidDataException: Angka ajaib di header GZip tidak benar. Pastikan Anda melewati aliran GZip ..

Saya sekarang menyadari bahwa .zipfile tidak sama dengan .gzfile, dan itu GZiptidak sama dengan Zip.

Namun, karena saya dapat mengekstrak file dengan mengklik dua kali file zip secara manual dan kemudian mengklik tombol "Ekstrak semua file", saya pikir harus ada cara untuk melakukan itu dalam kode juga.

Karena itu saya sudah mencoba menggunakan Process.Start()path ke file zip sebagai input. Ini menyebabkan aplikasi saya membuka Window yang memperlihatkan konten dalam file zip. Tidak apa-apa, tetapi aplikasi akan diinstal pada server tanpa ada yang mengklik tombol "Ekstrak semua file".

Jadi, bagaimana cara mendapatkan aplikasi saya untuk mengekstrak file dalam file zip?

Atau adakah cara lain untuk melakukannya? Saya lebih suka melakukannya dalam kode, tanpa mengunduh perpustakaan atau aplikasi pihak ketiga; departemen keamanan tidak terlalu suka tentang itu ...

Petteri
sumber
12
Departemen keamanan Anda lebih bahagia dengan Anda menulis kode sendiri untuk sesuatu daripada menggunakan perpustakaan yang telah di-debug dan dipandang oleh banyak orang? Anda dapat menggunakan perpustakaan DAN "melakukannya dalam kode" (dapatkan sumber dan kompilasi sendiri) tetapi saya melihat reinventing the wheel sebagai masalah yang lebih besar daripada masalah keamanan yang ditimbulkan dengan menggunakan perpustakaan yang sudah dicoba dan benar.
Jared Updike
10
@ Jared - Ketika manajemen mendapat ide di kepala mereka ...
Steven Evers
4
Ada sedikit risiko untuk departemen keamanan jika Anda mendapatkan produk pihak ketiga. Cukup unduh dotnetzip dan ganti namanya "[masukkan nama perusahaan] .ziplibrary.dll"
Simon

Jawaban:

59

Kami telah menggunakan SharpZipLib dengan sukses di banyak proyek. Saya tahu ini alat pihak ketiga, tetapi kode sumber disertakan dan dapat memberikan wawasan jika Anda memilih untuk menemukan kembali roda di sini.

Chris Conway
sumber
3
Saya mencoba menggunakan SharpZipLib dan bekerja dengan baik. Saya kira saya harus melihat apakah larangan terhadap libs dan apss pihak ketiga adalah aturan ketat atau lebih dari garis pedoman.
Petteri
10
Saya tidak tahu tentang perusahaan Anda, tetapi pengalaman saya adalah selalu ada kemungkinan untuk mendapatkan pengecualian dari aturan semacam itu jika Anda menulis deskripsi kasus bisnis tentang mengapa Anda menginginkan pengecualian. Tunjukkan penghematan biaya v. DIY, serta fakta bahwa sumber dapat diperiksa. Sebagai cadangan, Anda sering dapat memperoleh izin untuk menggunakan sumbernya bahkan jika mereka tidak mengizinkan Anda menggunakan dll - maka kompilasi sendiri (atau setidaknya bagian yang benar-benar harus Anda gunakan ...).
RolandTumble
Anda tidak harus menggunakan perpustakaan eksternal untuk membuka kompresi file zip, Anda bisa menggunakan Shell32 dari System32. Silakan lihat stackoverflow.com/a/43066281/948694
arturn
490

Dengan .NET 4.5 Anda sekarang dapat unzip file menggunakan .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);
    }
  }
}

Kode di atas diambil langsung dari dokumentasi Microsoft: http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx

ZipFileterkandung dalam majelis System.IO.Compression.FileSystem. (Terima kasih nateirvin ... lihat komentar di bawah)

bsara
sumber
118
BTW, ZipFileterkandung dalam majelis System.IO.Compression.FileSystem.
nateirvin
73
Yang berarti bahwa Anda perlu menambahkan referensi DLL ke perakitan kerangka kerja System.IO.Compression.FileSystem.dll.
Chris Schiffhauer
bagaimana dengan file .rar. kode di atas gagal mengekstrak file .rar.
Raghu
1
Saya mencoba ini di api web inti asp.net saya, membaca entri pertama baik-baik saja, tetapi pada entri kedua selalu memberikan kesalahan A local file header is corrupt. Adakah yang memikirkan hal ini?
SoftSan
Sama dengan @SoftSan. Saya juga mendapat kesalahan itu. Apa yang harus dilakukan?
Kaya
101

Untuk .Net 4.5+

Tidak selalu diinginkan untuk menulis file yang tidak dikompresi ke disk. Sebagai pengembang ASP.Net, saya harus mengutak-atik izin untuk memberikan hak bagi aplikasi saya untuk menulis ke sistem file. Dengan bekerja dengan stream dalam memori, saya dapat menghindari semua itu dan membaca file secara langsung:

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

Atau, Anda masih bisa menulis file yang sudah dikompresi ke disk dengan memanggil ExtractToFile():

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

Untuk menggunakan ZipArchivekelas, Anda perlu menambahkan referensi ke System.IO.Compressionnamespace dan System.IO.Compression.FileSystem.

Mister Epic
sumber
8
Apakah benar-benar membutuhkan MSFT hingga 4,5+ untuk menambahkan dekompresor asli?
John Peters
2
@JohnPeters GZipStream ditambahkan kembali .Net 2.0 ( msdn.microsoft.com/en-us/library/… ). Namun, itu tidak membuatnya mudah untuk bekerja dengan banyak file dalam arsip di memori. ZipArchiveObjek baru cocok dengan tagihan.
Pak Epic
1
Ini adalah alternatif yang sangat baik karena memungkinkan unzip tanpa menggunakan sistem file (dalam kasus saya saya bekerja dengan sumber daya yang tertanam), dan itu juga bukan ekstensi pihak ketiga.
ANeves
1
Mengapa saya harus menggunakan foreachperulangan ExtractToFileketika saya hanya dapat menggunakan ZipFile.ExtractToDirectory(inputFile, outputDir);Apa keuntungan dari metode pertama?
The Fluffy Robot
1
di .NET 4.6.1 saya tidak bisa mendapatkan 'ZipArchive' dari 'System.IO.Compression.FileSystem', ada Gagasan?
Ravi Anand
55

Gratis, dan tidak ada file DLL eksternal. Semuanya ada dalam satu file CS. Satu unduhan hanyalah file CS, unduhan lain adalah contoh yang sangat mudah dimengerti. Baru saja mencobanya hari ini dan saya tidak percaya betapa mudahnya pengaturannya. Ini berhasil pada percobaan pertama, tidak ada kesalahan, tidak apa-apa.

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

Lukas
sumber
Berbicara terlalu cepat! Saya ingin mengembang file dari aliran pengunduhan http secara instan. Ini tidak berfungsi karena menggunakan operasi Seek on the stream :( Yah, terima kasih pada kode sumbernya, saya bisa menulis ZipStream sendiri sekarang ...
oyophant
solusi terbaik untuk masalah saya, karena saya menulis aplikasi updater dan saya tidak bisa melibatkan DLL dalam proses ekstraksi sejak saat itu saya harus memperbarui mereka juga .... ini bagus. terima kasih!
Niklas
27

Gunakan perpustakaan DotNetZip di http://www.codeplex.com/DotNetZip

perpustakaan kelas dan toolset untuk memanipulasi file zip. Gunakan VB, C # atau bahasa .NET apa pun untuk dengan mudah membuat, mengekstrak, atau memperbarui file zip ...

DotNetZip bekerja pada PC dengan .NET Framework penuh, dan juga berjalan pada perangkat seluler yang menggunakan .NET Compact Framework. Buat dan baca file zip dalam VB, C #, atau bahasa .NET apa pun, atau lingkungan skrip apa pun ...

Jika yang Anda inginkan adalah kelas DeflateStream atau GZipStream yang lebih baik untuk menggantikan yang dibangun ke dalam .NET BCL, DotNetZip juga memilikinya. DeflateStream dan GZipStream dari DotNetZip tersedia dalam rakitan mandiri, berdasarkan pada port .NET dari Zlib. Streaming ini mendukung level kompresi dan memberikan kinerja yang jauh lebih baik daripada kelas bawaan. Ada juga ZlibStream untuk menyelesaikan set (RFC 1950, 1951, 1952) ...

Sam Axe
sumber
1
Hmmm ... Tapi itu perpustakaan pihak ketiga!
Petteri
30
Betapa taatnya Anda. Kecuali jika Anda ingin menghabiskan beberapa bulan mengimplementasikan pembaca file Zip Anda sendiri, itu pilihan terbaik Anda.
Sam Axe
Yang ini jauh lebih baik daripada SharpZipLib
Kugel
5
Anda mengajukan pertanyaan kepada saya tentang jawaban yang hampir berumur 5 tahun. Lakukan beberapa penelitian. Saya yakin Anda akan menemukan jawabannya.
Sam Axe
2
@ PhilCooper Ini adalah pertanyaan yang sangat lama saya sarankan menggunakan System.IO.Compression.ZipFile bawaan. IIRC Saya memiliki pengalaman yang sangat buruk dengan SharpZipLib di masa lalu berdasarkan pengalaman saya menghasilkan ribuan zip dengan cepat.
Kugel
9
String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

Untuk menggunakan kelas ZipFile, Anda harus menambahkan referensi ke perakitan System.IO.Compression.FileSystem di proyek Anda

Mahadev Mane
sumber
2

File zip standar biasanya menggunakan algoritma deflate.

Untuk mengekstrak file tanpa menggunakan perpustakaan pihak ketiga menggunakan DeflateStream. Anda akan memerlukan sedikit lebih banyak informasi tentang format arsip file zip karena Microsoft hanya menyediakan algoritma kompresi.

Anda juga dapat mencoba menggunakan zipfldr.dll. Ini adalah perpustakaan kompresi Microsoft (folder terkompresi dari menu Kirim ke). Tampaknya menjadi perpustakaan com tetapi tidak berdokumen. Anda mungkin bisa membuatnya bekerja untuk Anda melalui eksperimen.

Kenneth Cochran
sumber
Saya mencoba kelas DeflateStream. Kali ini saya mendapatkan System.IO.InvalidDataException: Panjang blok tidak cocok dengan pelengkapnya ..
Petteri
Seperti yang saya katakan di atas, Microsoft hanya menyediakan algoritma. Anda juga perlu info tentang format arsip zip. en.wikipedia.org/wiki/ZIP_(file_format) harus membantu Anda memulai. Lihat referensi di bagian bawah halaman untuk tautan ke info yang lebih rinci.
Kenneth Cochran
2
Saya juga sengaja menemukan System.IO.Packaging.Package di .NET 3.5. Sepertinya itu dapat melakukan trik meskipun tidak sangat intuitif.
Kenneth Cochran
2

Saya menggunakan ini untuk zip atau unzip banyak file. Hal-hal Regex tidak diperlukan, tetapi saya menggunakannya untuk mengubah cap tanggal dan menghapus garis bawah yang tidak diinginkan. Saya menggunakan string kosong dalam string Compress >> zipPath untuk mengawali sesuatu ke semua file jika diperlukan. Juga, saya biasanya berkomentar Kompres () atau Dekompresi () berdasarkan apa yang saya lakukan.

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);
            }
        }


    }
}
Phyllip Hamby
sumber
Ini membutuhkan dot net 4.5 - hanya catatan sebagai orang lain yang menjawab dengan ZipFile dicatat dan saya masih menggunakan 3,5.
Thronk
2

Ini akan melakukannya System.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)

Ilya Kochetov
sumber
1

Dari sini :

Objek GZipStream terkompresi yang ditulis ke file dengan ekstensi .gz dapat didekompresi menggunakan banyak alat kompresi umum; Namun, kelas ini secara inheren tidak menyediakan fungsionalitas untuk menambahkan file ke atau mengekstraksi file dari arsip .zip.

RedWolves
sumber
1

Anda dapat melakukan semuanya dalam. NET 3.5 menggunakan DeflateStream. Hal yang kurang dalam. NET 3.5 adalah kemampuan untuk memproses bagian header file yang digunakan untuk mengatur file zip. PKWare telah menerbitkan informasi ini, yang dapat Anda gunakan untuk memproses file zip setelah Anda membuat struktur yang digunakan. Ini tidak terlalu berat, dan ini merupakan praktik yang baik dalam membangun alat tanpa menggunakan kode pihak ke-3.

Itu bukan jawaban satu baris, tetapi sepenuhnya bisa dilakukan jika Anda bersedia dan dapat mengambil waktu sendiri. Saya menulis sebuah kelas untuk melakukan ini dalam beberapa jam dan apa yang saya dapatkan dari itu adalah kemampuan untuk zip dan unzip file menggunakan. NET 3.5 saja.

Michael Blake
sumber
0

Saya mengetahui tentang hal ini (paket Unzip di NuGet) hari ini, karena saya bertemu dengan bug keras di DotNetZip, dan saya menyadari belum ada banyak pekerjaan yang dilakukan pada DotNetZip selama dua tahun terakhir.

Paket Unzip ramping, dan berhasil bagi saya - tidak memiliki bug yang dimiliki DotNetZip. Juga, itu adalah file yang cukup kecil, mengandalkan Microsoft BCL untuk dekompresi yang sebenarnya. Saya dapat dengan mudah membuat penyesuaian yang saya butuhkan (untuk dapat melacak kemajuan sambil mendekompresi). Saya merekomendasikannya.

Per Lundberg
sumber
0

Dari Sumber Embed:

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

Sampai sekarang, saya menggunakan proses cmd untuk mengekstrak file .iso, menyalinnya ke jalur sementara dari server dan diekstraksi pada usb stick. Baru-baru ini saya menemukan bahwa ini bekerja dengan sempurna dengan .iso yang kurang dari 10GB. Untuk iso seperti 29GB metode ini macet entah bagaimana.

    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());
Răzvan Bălan
sumber
0

Anda dapat menggunakan Info-unzip cod command line. Anda hanya perlu mengunduh unzip.exe dari situs web resmi 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; }
    }        
Arun kumar
sumber