web-dev-qa-db-ja.com

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

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

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

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

.Zipファイルは.gzファイルと同じではなく、GZipZipと同じではないことがわかりました。

ただし、zipファイルを手動でダブルクリックして[すべてのファイルを抽出]ボタンをクリックすることでファイルを抽出できるため、コードでも同様の方法が必要だと思います。

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

では、zipファイル内のファイルを抽出するようにアプリを取得するにはどうすればよいですか?

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

198
Petteri

多くのプロジェクトで SharpZipLib を使用しました。サードパーティのツールであることは知っていますが、ソースコードが含まれており、ここで車輪を再発明することを選択した場合、ある程度の洞察を提供できます。

52
Chris Conway

。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 ...下のコメントを参照)

448
bsara

。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への参照を追加する必要があります。

77
Mister Epic

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

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

51
Lukas

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)...

27
Sam Axe
String ZipPath = @"c:\my\data.Zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

ZipFileクラスを使用するには、プロジェクトにSystem.IO.Compression.FileSystemアセンブリへの参照を追加する必要があります

9
Mahadev Mane

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

サードパーティのライブラリを使用せずにファイルを抽出するには、DeflateStreamを使用します。 Microsoftは圧縮アルゴリズムのみを提供しているため、Zipファイルアーカイブ形式についてもう少し情報が必要になります。

Zipfldr.dllを使用することもできます。これは、Microsoftの圧縮ライブラリ([送信]メニューの圧縮フォルダー)です。 comライブラリのように見えますが、文書化されていません。あなたは、実験を通してそれを機能させることができるかもしれません。

2
Kenneth Cochran

これでSystem.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)が実行されます

1
Ilya Kochetov

これを使用して、複数のファイルを圧縮または解凍します。 Regexのものは必要ありませんが、日付スタンプを変更し、不要なアンダースコアを削除するために使用します。圧縮>> 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);
            }
        }


    }
}
1
Phyllip Hamby

DeflateStreamを使用して、.NET 3.5内ですべて実行できます。 .NET 3.5に欠けているのは、zipファイルを整理するために使用されるファイルヘッダーセクションを処理する機能です。 PKWareはこの情報を公開しています。この情報を使用して、使用する構造を作成した後にZipファイルを処理できます。特に面倒なことではなく、サードパーティのコードを使用せずにツールを構築することをお勧めします。

それは一行の答えではありませんが、あなたが喜んで自分で時間を取ることができれば完全に実行可能です。数時間でこれを行うためのクラスを作成しましたが、そこから得たのは、.NET 3.5のみを使用してファイルを圧縮および解凍する機能です。

1
Michael Blake

ここ から:

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

1
RedWolves

これまで、.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
Răzvan Bălan

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; }
    }        
0
Arun kumar

DotNetZipでハードバグに遭遇したので、今日 this one (NuGetでパッケージを解凍)について知りました。年。

Unzipパッケージは無駄がなく、仕事をしてくれました-DotNetZipにあったバグはありませんでした。また、実際の解凍にはMicrosoft BCLに依存する、かなり小さなファイルでした。必要な調整を簡単に行うことができました(解凍中に進行状況を追跡できるようにするため)。私はそれをお勧めします。

0
Per Lundberg

Embed Ressourcesから:

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