.net에서 프로그래밍 방식으로 파일 압축 해제


221

압축 파일을 프로그래밍 방식으로 압축 해제하려고합니다.

System.IO.Compression.GZipStream.NET 에서 클래스를 사용해 보았지만 앱이 실행될 때 (실제로 단위 테스트)이 예외가 발생합니다.

System.IO.InvalidDataException : GZip 헤더의 매직 번호가 올바르지 않습니다. GZip 스트림을 전달하고 있는지 확인하십시오.

지금은 실현 .zip파일이 동일하지 않습니다 .gz파일 및 그 GZip와 동일하지 않습니다 Zip.

그러나 압축 파일을 수동으로 두 번 클릭 한 다음 "모든 파일 추출"버튼을 클릭하여 파일을 추출 할 수 있기 때문에 코드에서도 파일을 추출하는 방법이 있어야한다고 생각합니다.

따라서 Process.Start()압축 파일의 경로를 입력 으로 사용하려고했습니다 . 이로 인해 앱이 압축 파일의 내용을 보여주는 창을 열게됩니다. 괜찮습니다. 그러나 "모든 파일 추출"버튼을 클릭하지 않아도 서버에 앱이 설치됩니다.

그렇다면 앱에서 압축 파일의 파일을 추출하려면 어떻게해야합니까?

아니면 다른 방법이 있습니까? 타사 라이브러리 또는 앱을 다운로드하지 않고 코드로 작성하는 것을 선호합니다. 보안 부서는 그것에 대해 너무 화려하지 않습니다 ...


12
보안 부서는 아마도 많은 사람들이 디버그하고 살펴본 라이브러리를 사용하는 것보다 자신의 코드를 작성하는 것이 더 행복합니까? 라이브러리를 사용하고 "코드로 작성"(소스를 가져 와서 직접 컴파일) 할 수 있지만, 시도되고 진정한 라이브러리를 사용하여 발생하는 보안 문제보다 휠을 더 큰 문제로 재창조하는 것으로 보입니다.
Jared Updike

10
@Jared-경영진이 아이디어를 얻었을 때 ...
Steven Evers

4
타사 제품을 구입하면 보안 부서의 위험이 줄어 듭니다. dotnetzip을 다운로드하고 "[insert company name] .ziplibrary.dll"
Simon

답변:


59

많은 프로젝트에서 SharpZipLib을 성공적으로 사용 했습니다. 나는 그것이 타사 도구라는 것을 알고 있지만, 소스 코드가 포함되어 있으며 바퀴를 재발 명하기로 선택한 경우 통찰력을 제공 할 수 있습니다.


3
SharpZipLib을 사용해 보았지만 정상적으로 작동했습니다. 타사 라이브러리 및 aps에 대한 금지가 엄격한 규칙 이상인지 여부를 확인해야한다고 생각합니다.
Petteri 2016 년

10
나는 당신의 회사에 대해 모른다. 그러나 나의 경험은 항상 당신이 예외를 원하는 이유에 대한 비즈니스 사례 설명 을 작성한다면 그런 종류의 규칙에 대한 예외를 얻는 것이 가능하다는 것이 었습니다 . 비용 절감 vs. DIY와 소스를 조사 할 수 있다는 사실을 지적하십시오. 폴백으로 dll을 사용하지 못하게하더라도 소스를 사용할 수있는 권한을 얻을 수 있습니다. 그런 다음 직접 컴파일해야합니다 (또는 적어도 실제로 사용해야하는 부분은 ...).
RolandTumble

압축 파일을 압축 해제하기 위해 외부 라이브러리를 사용할 필요가 없습니다. System32의 Shell32를 사용할 수 있습니다. 참조하시기 바랍니다 stackoverflow.com/a/43066281/948694
arturn

490

.NET 4.5 할 수 있습니다 .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);
    }
  }
}

위 코드는 Microsoft 설명서에서 직접 가져 왔습니다. http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx

ZipFile어셈블리에 포함되어 System.IO.Compression.FileSystem있습니다. (감사합니다 nateirvin ... 아래 의견 참조)


118
BTW ZipFile는 어셈블리에 포함되어 System.IO.Compression.FileSystem있습니다.
nateirvin

73
이는 프레임 워크 어셈블리에 DLL 참조를 추가해야 함을 의미합니다 System.IO.Compression.FileSystem.dll.
Chris Schiffhauer

.rar 파일은 어떻습니까? 위의 코드는 .rar 파일을 추출하지 못합니다.
Raghu

1
나는 이것을 asp.net 핵심 웹 API에서 시도했지만 첫 번째 항목은 잘 읽었지만 두 번째 항목에서는 항상 오류가 발생 A local file header is corrupt합니다. 그래도 이것에?
SoftSan

@SoftSan과 동일합니다. 나는 또한 그 오류를 얻었다. 무엇을해야합니까?
Rich

101

.Net 4.5 이상

압축되지 않은 파일을 디스크에 쓰는 것이 항상 바람직한 것은 아닙니다. ASP.Net 개발자는 응용 프로그램이 파일 시스템에 쓸 수있는 권한을 부여 할 수있는 권한으로 바이올린을 사용해야합니다. 메모리의 스트림으로 작업함으로써 모든 것을 회피하고 파일을 직접 읽을 수 있습니다.

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

또는 다음을 호출하여 압축 해제 된 파일을 디스크에 쓸 수 있습니다 ExtractToFile().

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

ZipArchive클래스 를 사용하려면 System.IO.Compression네임 스페이스 및에 대한 참조를 추가해야 합니다 System.IO.Compression.FileSystem.


8
네이티브 압축 풀기 프로그램을 추가하려면 4.5 이상으로 MSFT가 필요합니까?
John Peters

2
@JohnPeters GZipStream이 .Net 2.0 ( msdn.microsoft.com/en-us/library/… ) 에 다시 추가되었습니다 . 그러나 메모리의 아카이브에있는 여러 파일로 작업하기가 쉽지 않았습니다. 새로운 ZipArchive물건은 법안에 잘 맞습니다.
Mister Epic

1
이것은 파일 시스템 (내 경우에는 임베디드 리소스로 작업 중)을 사용하지 않고 압축을 풀 수 있으며 타사 확장이 아니기 때문에 특히 좋은 대안 입니다.
ANeves

1
사용할 수있을 때 foreach루프를 사용해야하는 이유 첫 번째 방법의 장점은 무엇입니까? ExtractToFileZipFile.ExtractToDirectory(inputFile, outputDir);
플러피 로봇

1
.NET 4.6.1에서는 'System.IO.Compression.FileSystem'에서 'ZipArchive'를 얻을 수 없습니다.
라비 아난드

55

무료이며 외부 DLL 파일이 없습니다. 모든 것이 하나의 CS 파일에 있습니다. 하나의 다운로드는 CS 파일 일 뿐이고 다른 하나의 다운로드는 이해하기 쉬운 예입니다. 오늘 시도했지만 설치가 얼마나 간단한 지 믿을 수 없습니다. 첫 시도, 오류 없음, 아무것도하지 않았습니다.

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


너무 빨리 스포크! http 다운로드 스트림에서 파일을 즉시 팽창시키고 싶습니다. 그 이후이 작동하지 않음 ... 난 지금 내 자신의 ZipStream 쓸 수있는 소스 코드에 스트림 :( 음, 덕분에 작업을 탐색 사용
oyophant

내 문제에 대한 최상의 해결책은 업데이터 응용 프로그램을 작성하고 추출 프로세스에 DLL을 포함시킬 수 없기 때문에 그 이후에도 업데이트해야합니다. ... 이것은 좋습니다. 감사합니다!
Niklas

27

http://www.codeplex.com/DotNetZip 의 DotNetZip 라이브러리를 사용 하십시오.

zip 파일 조작을위한 클래스 라이브러리 및 도구 세트. VB, C # 또는 .NET 언어를 사용하여 zip 파일을 쉽게 생성, 추출 또는 업데이트하십시오 ...

DotNetZip은 전체 .NET Framework가 설치된 PC에서 작동하며 .NET Compact Framework를 사용하는 모바일 장치에서도 실행됩니다. VB, C # 또는 .NET 언어 또는 스크립팅 환경에서 zip 파일을 작성하고 읽습니다.

.NET BCL에 내장 된 클래스를 대체하기 위해 더 나은 DeflateStream 또는 GZipStream 클래스 만 있으면 DotNetZip도 있습니다. DotNetZip의 DeflateStream 및 GZipStream은 Zlib의 .NET 포트를 기반으로 독립 실행 형 어셈블리로 제공됩니다. 이 스트림은 압축 수준을 지원하고 내장 클래스보다 훨씬 우수한 성능을 제공합니다. 세트를 완료하기위한 ZlibStream도 있습니다 (RFC 1950, 1951, 1952) ...


1
흠 ... 그러나 그것은 제 3의 도서관입니다!
Petteri 2016 년

30
당신을 얼마나 잘 관찰합니까? 자신의 Zip 파일 리더를 구현하는 데 몇 개월을 소비하고 싶지 않다면 최선의 선택입니다.
Sam Ax

이것은 SharpZipLib보다 훨씬 좋습니다
Kugel

5
거의 5 년이 지난 답변에 대해 질문하고 있습니다. 조사 좀 해봐. 나는 당신이 대답을 찾을 것이라고 확신합니다.
Sam Ax

2
@PhilCooper 이것은 내장 된 System.IO.Compression.ZipFile을 사용하는 것이 가장 오래된 질문입니다. IIRC 나는 과거에 수천 개의 지퍼를 생산 한 경험을 바탕으로 과거에 SharpZipLib에 대해 나쁜 경험을했습니다.
Kugel

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

ZipFile 클래스를 사용하려면 프로젝트에서 System.IO.Compression.FileSystem 어셈블리에 대한 참조를 추가해야합니다.



2

표준 zip 파일은 일반적으로 수축 알고리즘을 사용합니다.

타사 라이브러리를 사용하지 않고 파일을 추출하려면 DeflateStream을 사용하십시오. Microsoft는 압축 알고리즘 만 제공하므로 zip 파일 아카이브 형식에 대한 추가 정보가 필요합니다.

zipfldr.dll을 사용해 볼 수도 있습니다. Microsoft의 압축 라이브러리입니다 (보내기 메뉴에서 압축 된 폴더). com 라이브러리 인 것처럼 보이지만 문서화되어 있지 않습니다. 실험을 통해 효과를 얻을 수 있습니다.


DeflateStream 클래스를 시도하고 있습니다. 이번에는 System.IO.InvalidDataException : 블록 길이가 보완과 일치하지 않습니다.
Petteri

위에서 말했듯이 Microsoft는 알고리즘 만 제공했습니다. Zip 보관 형식에 대한 정보도 필요합니다. en.wikipedia.org/wiki/ZIP_(file_format) 를 시작하십시오. 자세한 정보에 대한 링크는 페이지 하단의 참조를 참조하십시오.
케네스 코크란

2
또한 .NET 3.5에서 System.IO.Packaging.Package를 우연히 발견했습니다. 매우 직관적이지는 않지만 트릭을 수행하는 것처럼 보입니다.
케네스 코크란

2

여러 파일을 압축하거나 압축을 풀 때 사용합니다. 정규식 물건은 필요하지 않지만 날짜 스탬프를 변경하고 원치 않는 밑줄을 제거하는 데 사용합니다. 필요한 경우 Compress >> zipPath 문자열의 빈 문자열을 사용하여 모든 파일에 접두사를 붙입니다. 또한 나는 보통 내가하고있는 일에 따라 Compress () 또는 Decompress ()를 주석 처리합니다.

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


    }
}

이것은 닷넷 4.5가 필요합니다-ZipFile로 응답 한 다른 사람들이 언급했듯이 여전히 3.5를 사용하고 있습니다.
Thronk


1

에서 여기 :

확장자가 .gz 인 파일에 기록 된 압축 된 GZipStream 객체는 많은 일반적인 압축 도구를 사용하여 압축 해제 할 수 있습니다. 그러나이 클래스는 기본적으로 .zip 아카이브에서 파일을 추가하거나 파일을 추출하기위한 기능을 제공하지 않습니다.


1

DeflateStream을 사용하여 .NET 3.5 내에서 모두 수행 할 수 있습니다. .NET 3.5에서 부족한 점은 압축 파일을 구성하는 데 사용되는 파일 헤더 섹션을 처리하는 기능입니다. PKWare는이 정보를 공개했으며,이 정보는 사용 된 구조를 작성한 후 zip 파일을 처리하는 데 사용할 수 있습니다. 특히 번거롭지 않으며 타사 코드를 사용하지 않고 공구를 제작하는 것이 좋습니다.

한 줄짜리 대답은 아니지만 시간을내어 스스로 기꺼이 할 수 있다면 완전히 할 수 있습니다. 몇 시간 안에이 작업을 수행하는 클래스를 작성했으며 그로부터 얻은 것은 .NET 3.5 만 사용하여 파일을 압축 및 압축 해제하는 기능입니다.


0

나는에 대해 알게 이건 내가 DotNetZip에 하드 버그에 달려 있기 때문에, (NuGet에 압축을 풀고 패키지)는 오늘, 나는 많은 일이 지난 2 년 동안 DotNetZip에서 수행 정말이되지 않았습니다 깨달았다.

Unzip 패키지는 간결하고 나에게 도움이되었습니다. DotNetZip의 버그는 없었습니다. 또한 실제 압축 해제를 위해 Microsoft BCL에 의존하는 상당히 작은 파일이었습니다. 압축을 풀면서 진행 상황을 추적 할 수 있도록 필요한 조정 작업을 쉽게 수행 할 수있었습니다. 난 그것을 추천 해.


0

임베드 리소스에서 :

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

0

지금까지 .iso 파일을 추출하기 위해 cmd 프로세스를 사용하여 서버에서 임시 경로로 복사하고 USB 스틱에서 추출했습니다. 최근에 10Gb 미만의 .iso와 완벽하게 작동한다는 것을 알았습니다. 29Gb와 같은 ISO의 경우이 방법은 어떻게 든 붙어 있습니다.

    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

Info-unzip 명령 줄 cod를 사용할 수 있습니다 . Info-unzip 공식 웹 사이트에서 unzip.exe 만 다운로드하면됩니다.

 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; }
    }        
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.