プログラムで.netにファイルを解凍する


221

プログラムで圧縮ファイルを解凍しようとしています。

System.IO.Compression.GZipStream.NETでクラスを使用しようとしましたが、アプリを実行すると(実際には単体テスト)、次の例外が発生します。

System.IO.InvalidDataException:GZipヘッダーのマジックナンバーが正しくありません。GZipストリームを渡していることを確認してください。

私は今、.zipファイルがファイルと同じ.gzGZipはなく、それがと同じではないことに気づきましたZip

ただし、zipファイルを手動でダブルクリックして[すべてのファイルを抽出]ボタンをクリックすることでファイルを抽出できるため、コードでもそれを実行する方法があるはずです。

したがって、私はProcess.Start()圧縮ファイルへのパスを入力として使用しようとしました。これにより、私のアプリは、zipファイルの内容を表示するウィンドウを開きます。これで問題ありませんが、アプリはサーバーにインストールされ、「Extract all files」ボタンをクリックする必要はありません。

では、圧縮されたファイルからファイルを抽出する方法をアプリに教えてください。

それとも別の方法がありますか?私はサードパーティのライブラリやアプリをダウンロードせずに、コードでそれを行うことを好みます。セキュリティ部門はそれについてあまり空想ではありません...


12
あなたのセキュリティ部門は、おそらく多くの目でデバッグされて見られているライブラリを使用するよりも、何かのために独自のコードを書くことに満足していますか?ライブラリを使用して、「コードで実行」する(ソースを取得して自分でコンパイルする)ことができますが、ホイールを再発明することは、実証済みのライブラリを使用することによって引き起こされるセキュリティ問題よりも大きな問題であると思います。
Jared Updike、

10
@Jared-経営陣が頭に浮かんだとき
スティーブンエバーズ

4
サードパーティ製品を入手すれば、セキュリティ部門のリスクは少なくなります。dotnetzipをダウンロードして、名前を「[会社名を挿入] .ziplibrary.dll」に変更します
Simon

回答:


59

SharpZipLibは多くのプロジェクトで使用されています。私はそれがサードパーティのツールであることを知っていますが、ソースコードが含まれており、ここでホイールを再発明することを選択した場合、いくつかの洞察を提供する可能性があります。


3
SharpZipLibを使用してみましたが、問題なく動作しました。サードパーティのlibsとapssに対する禁止が厳格なルールなのか、それともガイドライン以上のものなのかを確認する必要があると思います。
ペッテリ

10
私はあなたの会社については知りませんが、例外が必要な理由のビジネスケースの説明を書くと、この種のルールの例外が発生する可能性があるという経験が常にあります。コスト削減対DIY、および出所を調査できるという事実を指摘します。フォールバックとして、dllを使用させない場合でも、ソースを使用するための許可を得ることができます-次に、自分でコンパイルするか、少なくとも実際に使用する必要がある部分をコンパイルします。
RolandTumble 2009年

外部ライブラリを使用してzipファイルを解凍する必要はありません。System32のShell32を使用できます。stackoverflow.com/a/43066281/948694を
arturn 2017年

490

.NET 4.5の.NETフレームワークを使用して次のことができ、今解凍ファイル:

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
ところで、ZipFileアセンブリに含まれていSystem.IO.Compression.FileSystemます。
nateirvin 2013

73
つまり、フレームワークアセンブリにDLL参照を追加する必要がありますSystem.IO.Compression.FileSystem.dll
Chris Schiffhauer、2013

.rarファイルについてはどうでしょう。上記のコードは.rarファイルの抽出に失敗します。
ラグー2017

1
私のasp.netコアWeb APIでこれを試しましたが、最初のエントリは正常に読み取られましたが、2番目のエントリでは常にエラーが発生しましたA local file header is corrupt。これについてはどうですか?
SoftSan

@SoftSanと同じです。私もそのエラーを得ました。何をすべきか?
リッチ

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オブジェクトは法案にうまく適合します。
ミスターエピック

1
これは、ファイルシステムを使用せずに解凍できるため(特に、埋め込みリソースで作業しているため)、特に優れた代替手段であり、サードパーティの拡張機能でもありません。
ANeves、2015年

1
なぜ私が使用する必要がありますforeachへのループをExtractToFile私は使用することができたときにZipFile.ExtractToDirectory(inputFile, outputDir);第一の方法の利点は何ですか?
ふわふわロボット

1
.NET 4.6.1では、「System.IO.Compression.FileSystem」から「ZipArchive」を取得できません。
Ravi Anand

55

無料で、外部DLLファイルはありません。すべてが1つのCSファイルにあります。1つのダウンロードは単なるCSファイルであり、別のダウンロードは非常に理解しやすい例です。今日試してみただけで、セットアップが簡単だったなんて信じられません。それは最初の試行で機能し、エラーはなく、何もありませんでした。

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


スポークが早すぎます!HTTPダウンロードストリームのファイルをすぐに膨らませたいです。ストリームでSeek操作を使用しているため、これは機能しません:(まあ、ソースコードのおかげで、今すぐ独自の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
うーん...しかし、それはサードパーティのライブラリです!
ペッテリ

30
あなたのことをどれほど非常に順守しているか。独自のZipファイルリーダーを実装するために数か月を費やしたいと思わない限り、これが最良のオプションです。
サムアックス

これはSharpZipLibよりもはるかに優れています
Kugel

5
5年近く前の答えについて質問があります。いくつかの研究を行います。きっとあなたは答えを見つけるでしょう。
Sam Ax

2
@PhilCooperこれは、組み込みのSystem.IO.Compression.ZipFileを使用することをお勧めする非常に古い質問です。IIRC何千ものzipをその場で生成した経験に基づいて、過去にSharpZipLibで本当に悪い経験をしました。
Kugel


2

標準のzipファイルは通常、deflateアルゴリズムを使用します。

サードパーティのライブラリを使用せずにファイルを抽出するには、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 2014年


1

ここから:

拡張子が.gzのファイルに書き込まれた圧縮GZipStreamオブジェクトは、多くの一般的な圧縮ツールを使用して解凍できます。ただし、このクラスは本質的に、.zipアーカイブにファイルを追加したり、そこからファイルを抽出したりする機能を提供しません。


1

DeflateStreamを使用して、.NET 3.5内ですべて実行できます。.NET 3.5に欠けているのは、zipファイルの編成に使用されるファイルヘッダーセクションを処理する機能です。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ファイルを抽出し、サーバーから一時パスにコピーして、USBスティックに抽出するために、cmdプロセスを使用していました。最近、これが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公式Webサイトから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.