.Net'te dosyaları programlı olarak aç


221

Sıkıştırılmış bir dosyayı programlı olarak açmaya çalışıyorum.

System.IO.Compression.GZipStream.NET sınıf kullanmayı denedim , ama benim app (aslında bir birim sınama) çalıştığında ben bu istisna olsun:

System.IO.InvalidDataException: GZip başlığındaki sihirli sayı doğru değil. Bir GZip akışından geçtiğinizden emin olun.

Şimdi bir fark .zipdosyası aynı değildir .gzdosyanın ve bu GZipaynı değildir Zip.

Ancak, elle sıkıştırılmış dosyayı çift tıklatıp "Tüm dosyaları ayıkla" düğmesini tıklatarak dosyayı ayıklayabildiğim için, kodda da yapmanın bir yolu olması gerektiğini düşünüyorum.

Bu nedenle Process.Start()girdi olarak sıkıştırılmış dosyanın yolu ile kullanmaya çalıştım . Bu, uygulamamın sıkıştırılmış dosyadaki içeriği gösteren bir Pencere açmasına neden oluyor. Her şey yolunda, ancak uygulama "Tüm dosyaları ayıkla" düğmesine tıklamak için hiçbiri olmayan bir sunucuya yüklenecek.

Peki, uygulamamın sıkıştırılmış dosyalardaki dosyaları ayıklamasını nasıl sağlarım?

Yoksa bunu yapmanın başka bir yolu var mı? Herhangi bir üçüncü taraf kitaplık veya uygulama indirmeden kodda yapmayı tercih ederim; Güvenlik departmanı bu konuda çok süslü değil ...


12
Güvenlik departmanınız, hata ayıklanmış ve muhtemelen birçok göz tarafından bakılan bir kütüphane kullanmaktan başka bir şey için kendi kodunuzu yazmaktan memnun mu? Bir kütüphane kullanabilirsiniz VE "kodda bunu yapmak" (kaynak olsun ve kendiniz derlemek) ama ben yeniden denenmiş ve gerçek bir kütüphane kullanarak getirdiği herhangi bir güvenlik sorunlarından daha büyük bir sorun olarak tekerleği yeniden icat görüyorum.
Jared Updike

10
@Jared - Yönetim başlarına bir fikir geldiğinde ...
Steven Evers

4
Üçüncü taraf bir ürün alırsanız güvenlik departmanı için daha az risk vardır. Sadece dotnetzip'i indirin ve yeniden adlandırın [[şirket adını girin] .ziplibrary.dll "
Simon

Yanıtlar:


59

SharpZipLib'i birçok projede başarıyla kullandık . Bunun üçüncü taraf bir araç olduğunu biliyorum, ancak kaynak kodu dahil ve burada tekerleği yeniden icat etmeyi seçerseniz bazı bilgiler sağlayabilir.


3
SharpZipLib kullanmayı denedim ve iyi çalıştı. Sanırım üçüncü şahısların kütüphanelerine ve aps'lerine karşı yasağın katı bir kural mı yoksa daha çok bir kılavuz olup olmadığını görmek zorundayım.
Petteri

10
Şirketinizi bilmiyorum, ancak deneyimlerim her zaman , istisnayı neden istediğinize dair bir iş vakası açıklaması yazdıysanız, bu tür bir kuralın istisnasını alabilmeniz olmuştur . Maliyet tasarruflarına karşı DIY'ye ve kaynağın incelenebileceğine dikkat edin. Bir yedek olarak, dll'yi kullanmanıza izin vermese bile, kaynağı kullanmak için genellikle izin alabilirsiniz - o zaman sadece kendiniz (veya en azından gerçekten kullanmanız gereken parçalar ...) derleyin.
RolandTumble

Zip dosyalarını açmak için harici kitaplıklar kullanmanıza gerek yoktur, System32'den Shell32'yi kullanabilirsiniz. Lütfen bkz. Stackoverflow.com/a/43066281/948694
arturn

490

İle .NET 4.5 artık .NET çerçevesini kullanarak dosyaları açabilirsiniz:

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

Yukarıdaki kod doğrudan Microsoft'un belgelerinden alınmıştır: http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx

ZipFilemontajda bulunur System.IO.Compression.FileSystem. (Teşekkürler nateirvin ... aşağıdaki yoruma bakın)


118
BTW, ZipFilemontajda bulunur System.IO.Compression.FileSystem.
nateirvin

73
Bu, çerçeve derlemesine bir DLL başvurusu eklemeniz gerektiği anlamına gelir System.IO.Compression.FileSystem.dll.
Chris Schiffhauer

.rar dosyaları hakkında. Yukarıdaki kod .rar dosyalarını ayıklayamıyor.
Raghu

1
Bu benim asp.net core web api denedim, ilk giriş iyi okumak, ama ikinci girişte her zaman hata verir A local file header is corrupt. Bununla ilgili bir şey var mı?
SoftSan

@SoftSan ile aynı. Bu hatayı da aldım. Ne yapalım?
Zengin

101

Net 4.5+ için

Sıkıştırılmamış dosyanın diske yazılması her zaman istenmez. Bir ASP.Net geliştiricisi olarak, uygulamamın dosya sistemine yazma hakları vermek için izinlerle uğraşmak zorunda kalırım. Bellekteki akışlarla çalışarak, tüm bunları kaldırıp dosyaları doğrudan okuyabilirim:

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

Alternatif olarak, sıkıştırılmış dosyayı yine de arayarak diske yazabilirsiniz ExtractToFile():

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

ZipArchiveSınıfı kullanmak için System.IO.Compressionad alanına ve öğesine bir başvuru eklemeniz gerekir System.IO.Compression.FileSystem.


8
Doğal bir dekompresör eklemek MSFT'yi 4.5+'ye kadar sürdü mü?
John Peters

2
@JohnPeters GZipStream .Net 2.0 ( msdn.microsoft.com/en-us/library/… ) içine geri eklenmiştir . Ancak, bellekteki bir arşivde birden fazla dosyayla çalışmayı kolaylaştırmadı. Yeni ZipArchivenesne faturaya iyi uyuyor.
Bay Epic

1
Bu özellikle iyi bir alternatif çünkü dosya sistemini kullanmadan sıkıştırmayı açmaya izin veriyor (benim durumumda gömülü kaynaklarla çalışıyorum) ve aynı zamanda üçüncü taraf bir uzantı değil.
ANeves

1
Neden kullanabileceğim bir foreachdöngü ExtractToFilekullanmalıyım ZipFile.ExtractToDirectory(inputFile, outputDir);? İlk yöntemin avantajı nedir?
Fluffy Robot

1
.NET 4.6.1 'System.IO.Compression.FileSystem', herhangi bir Fikir 'ZipArchive' alamıyorum.
Ravi Anand

55

Ücretsiz ve harici DLL dosyaları yok. Her şey bir CS dosyasında. Bir indirme sadece CS dosyası, başka bir indirme çok kolay anlaşılır bir örnektir. Sadece bugün denedim ve kurulumun ne kadar basit olduğuna inanamıyorum. İlk denemede çalıştı, hata yok, hiçbir şey yok.

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


Çok erken konuştu! Anında bir http indirme akışından dosyaları şişirmek istiyorum. Akışta Seek işlemleri kullandığından bu çalışmaz :( Peki, kaynak kodu sayesinde şimdi kendi ZipStream'imi yazabilirim ...
oyophant

im bir güncelleyici uygulaması yazma ve o zamandan beri ben de güncellemek zorunda kalacak beri ayıklama sürecinde herhangi bir DLL'leri dahil edemem çünkü benim sorunum için en iyi çözüm .... Bu iyi. teşekkür ederim!
Niklas

27

Http://www.codeplex.com/DotNetZip adresindeki DotNetZip kütüphanesini kullanın

zip dosyalarını işlemek için sınıf kütüphanesi ve araç seti. Zip dosyalarını kolayca oluşturmak, ayıklamak veya güncellemek için VB, C # veya herhangi bir .NET dilini kullanın ...

DotNetZip, tam .NET Framework'e sahip PC'lerde çalışır ve ayrıca .NET Compact Framework kullanan mobil cihazlarda çalışır. VB, C # veya herhangi bir .NET dilinde veya herhangi bir komut dosyası ortamında zip dosyaları oluşturun ve okuyun ...

İstediğiniz tek şey, .NET BCL'de yerleşik olanı değiştirmek için daha iyi bir DeflateStream veya GZipStream sınıfı ise, DotNetZip de buna sahiptir. DotNetZip'in DeflateStream ve GZipStream, Zlib'in .NET portuna dayanan bağımsız bir montajda mevcuttur. Bu akışlar sıkıştırma düzeylerini destekler ve yerleşik sınıflardan çok daha iyi performans sunar. Seti tamamlamak için bir ZlibStream de var (RFC 1950, 1951, 1952) ...


1
Hmmm ... Ama bu üçüncü taraf bir kütüphane!
Petteri

30
Ne kadar dikkat ediyorsun. Kendi Zip dosya okuyucunuzu uygulayarak birkaç ay geçirmek istemiyorsanız, bu en iyi seçenektir.
Sam Axe

Bu bir SharpZipLib
Kugel

5
Bana neredeyse 5 yaşında olan bir cevap hakkında sorular soruyorsun. Biraz araştırma yap. Eminim bir cevap bulacaksın.
Sam Ax

2
@PhilCooper Bu yerleşik System.IO.Compression.ZipFile kullanmanızı tavsiye ettiğim çok eski bir soru. IIRC Geçmişte binlerce fermuar üretme deneyimime dayanarak geçmişte SharpZipLib ile gerçekten kötü deneyimler yaşadım.
Kugel

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

ZipFile sınıfını kullanmak için, projenizdeki System.IO.Compression.FileSystem derlemesine bir başvuru eklemeniz gerekir



2

Standart zip dosyaları normalde deflate algoritmasını kullanır.

Üçüncü taraf kitaplıkları kullanmadan dosyaları ayıklamak için DeflateStream kullanın. Microsoft yalnızca sıkıştırma algoritmasını sağladığı için zip dosyası arşiv biçimi hakkında biraz daha bilgiye ihtiyacınız olacak.

Ayrıca zipfldr.dll dosyasını kullanmayı deneyebilirsiniz. Bu, Microsoft'un sıkıştırma kitaplığıdır (Gönder menüsünden sıkıştırılmış klasörler). Bir com kütüphane gibi görünüyor ama belgesiz. Deneme yoluyla sizin için çalışmasını sağlayabilirsiniz.


DeflateStream sınıfını deniyorum. Bu sefer System.IO.InvalidDataException alıyorum: Blok uzunluğu tamamlayıcı ile eşleşmiyor ..
Petteri

Yukarıda söylediğim gibi, Microsoft yalnızca algoritmayı sağlamıştır. Zip arşiv biçimi hakkında da bilgi sahibi olmanız gerekir. en.wikipedia.org/wiki/ZIP_(file_format) başlamanız gerekir. Daha ayrıntılı bilgilere bağlantılar için sayfanın altındaki referanslara bakın.
Kenneth Cochran

2
Ayrıca .NET 3.5'te System.IO.Packaging.Package'a rastladım. Çok sezgisel olmasa da hile yapabilir gibi görünüyor.
Kenneth Cochran

2

Bunu birden çok dosyayı sıkıştırmak veya açmak için kullanıyorum. Regex şeyler gerekli değildir, ancak bunu tarih damgasını değiştirmek ve istenmeyen alt çizgileri kaldırmak için kullanıyorum. Ben gerekirse tüm dosyalara bir şey önek için sıkıştırmak >> zipPath dizesinde boş dize kullanın. Ayrıca, genellikle ne yaptığımı temel alarak Compress () veya Decompress () yorum.

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


    }
}

Bu nokta net 4.5 gerektirir - sadece ZipFile ile cevap diğerleri gibi kaydetti ve ben hala 3.5 kullanıyorum.
Thronk

2

Bu yapacak System.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)


1

Gönderen burada :

.Gz uzantılı bir dosyaya yazılan sıkıştırılmış GZipStream nesneleri, birçok yaygın sıkıştırma aracı kullanılarak açılabilir; ancak, bu sınıf doğal olarak .zip arşivlerine dosya eklemek veya bu dosyalardan dosya çıkarmak için işlevsellik sağlamaz.


1

Her şeyi DeflateStream kullanarak .NET 3.5 içinde yapabilirsiniz. .NET 3.5'te eksik olan şey, sıkıştırılmış dosyaları düzenlemek için kullanılan dosya başlığı bölümlerini işleme yeteneğidir. PKWare, kullanılan yapıları oluşturduktan sonra zip dosyasını işlemek için kullanabileceğiniz bu bilgileri yayınladı. Özellikle zahmetli değildir ve 3. taraf kodu kullanmadan takım oluşturmada iyi bir uygulamadır.

Tek satırlık bir cevap değil, ama zaman ayırmaya istekli ve yapabiliyorsanız tamamen yapılabilir. Birkaç saat içinde bunu yapmak için bir sınıf yazdım ve bu sadece NET 3.5 kullanarak dosyaları zip ve unzip yeteneği var.


0

Ben öğrendim bu bir ben DotNetZip sert hata koştu beri (Nuget Unzip paketi) bugün ve ben çok iş son iki yıldır DotNetZip yapılan gerçekten bu olmamıştır fark etti.

Unzip paketi yalın ve benim için işi yaptı - DotNetZip'in sahip olduğu bir hata yoktu. Ayrıca, gerçek dekompresyon için Microsoft BCL'ye dayanan oldukça küçük bir dosyaydı. Kolayca ihtiyacım olan ayarlamaları yapabilirim (açma işlemi sırasındaki ilerlemeyi takip edebilmek için). Bunu öneririm.


0

Gömülü Kaynaklardan:

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

0

Şimdiye kadar, .iso dosyasını ayıklamak, sunucudan geçici bir yola kopyalamak ve bir usb çubuğuna ayıklamak için cmd işlemleri kullanıyordum. Son zamanlarda bunun 10iso'dan daha az olan .iso ile mükemmel çalıştığını gördüm. 29 Gb gibi bir iso için bu yöntem bir şekilde takılıyor.

    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

Kullanabileceğiniz Info-unzip cod.you sadece Info-unzip resmi web sitesinden unzip.exe indirmeniz gerekir komut satırını.

 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; }
    }        
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.