web-dev-qa-db-ja.com

サードパーティAPIを使用せずにC#でファイルを圧縮するにはどうすればよいですか?

これは重複していないと確信しているので、しばらくお待ちください。

サードパーティのライブラリを使用せずに(Windowsで)ファイルをZip圧縮(C#)するにはどうすればよいですか?ネイティブのWindows呼び出しなどが必要です。私はプロセスを開始するという考えを本当に嫌いますが、絶対にやらなければならない場合はそうします。 PInovkeコールの方がはるかに良いでしょう。

それに失敗したら、私が本当に達成しようとしていることをお話ししましょう。ユーザーに1回のリクエストでドキュメントのコレクションをダウンロードさせる機能が必要です。これを達成する方法に関するアイデアはありますか?

165
Esteban Araya

.NET 3.5を使用していますか? ZipPackage クラスと関連クラスを使用できます。追加するファイルごとにMIMEタイプが必要なため、ファイルリストを圧縮するだけではありません。それはあなたが望むことをするかもしれません。

現在、これらのクラスを同様の問題に使用して、複数の関連ファイルをダウンロード用の単一ファイルにアーカイブしています。ファイル拡張子を使用して、ダウンロードファイルをデスクトップアプリに関連付けます。私たちが遭遇した小さな問題の1つは、クライアント側のコードで開くことができないため、7-Zipなどのサードパーティツールを使用してZipファイルを作成することができないことです-ZipPackageは、コンテンツタイプを記述する隠しファイルを追加します各コンポーネントファイル。そのコンテンツタイプファイルが見つからない場合、Zipファイルを開くことができません。

85
Brian Ensink

サードパーティのライブラリを使用せずに(Windowsで)ファイルをZip圧縮(C#)するにはどうすればよいですか?

4.5+フレームワークを使用している場合、 ZipArchive および ZipFile クラスがあります。

using (ZipArchive Zip = ZipFile.Open("test.Zip", ZipArchiveMode.Create))
{
    Zip.CreateEntryFromFile(@"c:\something.txt", "data/path/something.txt");
}

以下に参照を追加する必要があります。

  • System.IO.Compression
  • System.IO.Compression.FileSystem

Net46を対象とする.NET Coreの場合、次の依存関係を追加する必要があります。

  • System.IO.Compression
  • System.IO.Compression.ZipFile

Project.jsonの例:

"dependencies": {
  "System.IO.Compression": "4.1.0",
  "System.IO.Compression.ZipFile": "4.0.1"
},

"frameworks": {
  "net46": {}
}

.NET Core 2.0では、単純なusingステートメントを追加するだけで十分です。

  • System.IO.Compressionを使用;
279
GalacticJello

私は同じ状況にあり、サードパーティのライブラリではなく.NETを望んでいました。前述の別のポスターとして、ZipPackageクラス(.NET 3.5で導入)を使用するだけでは十分ではありません。 ZipPackageが機能するためには、アーカイブに追加する必要がある追加のファイルがあります。このファイルを追加すると、結果のZipパッケージをWindowsエクスプローラーから直接開くことができます-問題ありません。

必要なことは、[Content_Types] .xmlファイルをアーカイブのルートに追加することです。これには、含めるファイル拡張子ごとに「デフォルト」ノードを指定します。追加したら、Windowsエクスプローラーからパッケージを参照するか、プログラムで解凍してその内容を読み取ることができます。

[Content_Types] .xmlファイルの詳細については、次を参照してください。 http://msdn.Microsoft.com/en-us/magazine/cc163372.aspx

[Content_Types] .xml(正確な名前を付ける必要があります)ファイルのサンプルを次に示します。

<?xml version="1.0" encoding="utf-8" ?>
<Types xmlns=
    "http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="xml" ContentType="text/xml" /> 
  <Default Extension="htm" ContentType="text/html" /> 
  <Default Extension="html" ContentType="text/html" /> 
  <Default Extension="rels" ContentType=
    "application/vnd.openxmlformats-package.relationships+xml" /> 
  <Default Extension="jpg" ContentType="image/jpeg" /> 
  <Default Extension="png" ContentType="image/png" /> 
  <Default Extension="css" ContentType="text/css" /> 
</Types>

そして、Zipファイルを作成するためのC#:

var zipFilePath = "c:\\myfile.Zip"; 
var tempFolderPath = "c:\\unzipped"; 

    using (Package package = ZipPackage.Open(zipFilePath, FileMode.Open, FileAccess.Read)) 
    { 
        foreach (PackagePart part in package.GetParts()) 
        { 
            var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart('/'))); 
            var targetDir = target.Remove(target.LastIndexOf('\\')); 

            if (!Directory.Exists(targetDir)) 
                Directory.CreateDirectory(targetDir); 

            using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read)) 
            { 
                source.CopyTo(File.OpenWrite(target)); 
            } 
        } 
    } 

注意:

11
Joshua
    private static string CompressFile(string sourceFileName)
    {
        using (ZipArchive archive = ZipFile.Open(Path.ChangeExtension(sourceFileName, ".Zip"), ZipArchiveMode.Create))
        {
            archive.CreateEntryFromFile(sourceFileName, Path.GetFileName(sourceFileName));
        }
        return Path.ChangeExtension(sourceFileName, ".Zip");
    }
7
FLICKER

.NET 2.0アプリでは、 SharpZipLib を使用しました。使いやすく、オープンソース。

3
Tim Scarborough

Simon McKenzieの答え この質問に対する に基づいて、次のようなメソッドのペアを使用することをお勧めします。

    public static void ZipFolder(string sourceFolder, string zipFile)
    {
        if (!System.IO.Directory.Exists(sourceFolder))
            throw new ArgumentException("sourceDirectory");

        byte[] zipHeader = new byte[] { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

        using (System.IO.FileStream fs = System.IO.File.Create(zipFile))
        {
            fs.Write(zipHeader, 0, zipHeader.Length);
        }

        dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
        dynamic source = shellApplication.NameSpace(sourceFolder);
        dynamic destination = shellApplication.NameSpace(zipFile);

        destination.CopyHere(source.Items(), 20);
    }

    public static void UnzipFile(string zipFile, string targetFolder)
    {
        if (!System.IO.Directory.Exists(targetFolder))
            System.IO.Directory.CreateDirectory(targetFolder);

        dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
        dynamic compressedFolderContents = shellApplication.NameSpace(zipFile).Items;
        dynamic destinationFolder = shellApplication.NameSpace(targetFolder);

        destinationFolder.CopyHere(compressedFolderContents);
    }
}
1
mccdyl001

Windowsでできることのように見えます this ...

残念ながら、サードパーティのコンポーネントに移動しない限り、別のプロセスを開始することはできないと思います。

0
Dave Swersky

次の4つの関数をプロジェクトに追加します。

        public const long BUFFER_SIZE = 4096;
    public static void AddFileToZip(string zipFilename, string fileToAdd)
    {
        using (Package Zip = global::System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate))
        {
            string destFilename = ".\\" + Path.GetFileName(fileToAdd);
            Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
            if (Zip.PartExists(uri))
            {
                Zip.DeletePart(uri);
            }
            PackagePart part = Zip.CreatePart(uri, "", CompressionOption.Normal);
            using (FileStream fileStream = new FileStream(fileToAdd, FileMode.Open, FileAccess.Read))
            {
                using (Stream dest = part.GetStream())
                {
                    CopyStream(fileStream, dest);
                }
            }
        }
    }
    public static void CopyStream(global::System.IO.FileStream inputStream, global::System.IO.Stream outputStream)
    {
        long bufferSize = inputStream.Length < BUFFER_SIZE ? inputStream.Length : BUFFER_SIZE;
        byte[] buffer = new byte[bufferSize];
        int bytesRead = 0;
        long bytesWritten = 0;
        while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0)
        {
            outputStream.Write(buffer, 0, bytesRead);
            bytesWritten += bytesRead;
        }
    }
    public static void RemoveFileFromZip(string zipFilename, string fileToRemove)
    {
        using (Package Zip = global::System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate))
        {
            string destFilename = ".\\" + fileToRemove;
            Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
            if (Zip.PartExists(uri))
            {
                Zip.DeletePart(uri);
            }
        }
    }
    public static void Remove_Content_Types_FromZip(string zipFileName)
    {
        string contents;
        using (ZipFile zipFile = new ZipFile(File.Open(zipFileName, FileMode.Open)))
        {
            /*
            ZipEntry startPartEntry = zipFile.GetEntry("[Content_Types].xml");
            using (StreamReader reader = new StreamReader(zipFile.GetInputStream(startPartEntry)))
            {
                contents = reader.ReadToEnd();
            }
            XElement contentTypes = XElement.Parse(contents);
            XNamespace xs = contentTypes.GetDefaultNamespace();
            XElement newDefExt = new XElement(xs + "Default", new XAttribute("Extension", "sab"), new XAttribute("ContentType", @"application/binary; modeler=Acis; version=18.0.2application/binary; modeler=Acis; version=18.0.2"));
            contentTypes.Add(newDefExt);
            contentTypes.Save("[Content_Types].xml");
            zipFile.BeginUpdate();
            zipFile.Add("[Content_Types].xml");
            zipFile.CommitUpdate();
            File.Delete("[Content_Types].xml");
            */
            zipFile.BeginUpdate();
            try
            {
                zipFile.Delete("[Content_Types].xml");
                zipFile.CommitUpdate();
            }
            catch{}
        }
    }

そして、これらを次のように使用します。

foreach (string f in UnitZipList)
{
    AddFileToZip(zipFile, f);
    System.IO.File.Delete(f);
}
Remove_Content_Types_FromZip(zipFile);
0
Teemo