LoginSignup
0
2

C# - VisualStudioもライブラリも使わずにZipファイルを生成する

Last updated at Posted at 2020-07-30

環境

Windows10 (7も多分いけるはず)

コンパイル

事前にcscにパスを通しておく。
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe

compile.bat

csc /r:C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.IO.Compression.FileSystem.dll ^
    /r:C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.IO.Compression.dll %*

下記でコンパイルできる。
compile.bat ソース名.cs

ソースコード


using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.IO.Compression; // to use zip

class ZipTest : Form
{
    ZipTest()
    {
        var btn = new Button(){
            Size = new Size(200,25),
            Text = "Save zip file",
        };
        btn.Click += (s,e)=>{
            string destPath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "ZipTest_Output.zip");
            CreateZipFile(destPath);
        };
        Controls.Add(btn);

    }

    void CreateZipFile(string destZipPath)
    {
        try {
            //  ZipFile.Open で Zipを作成するとき、すでにファイルが存在していると例外が発生する。
            //  上書きしたい場合は、すでにファイルが存在する場合は削除しておく。
            // if (File.Exists(destZipPath)) {
            //     File.Delete(destZipPath);
            // }

            using( ZipArchive archive = ZipFile.Open(destZipPath, ZipArchiveMode.Create) ) {
                ZipArchiveEntry entry;

                entry = archive.CreateEntry("Test1.txt", CompressionLevel.Optimal);
                using (StreamWriter writer = new StreamWriter(entry.Open()))
                {
                    writer.WriteLine("FileContentSample-1");
                }

                entry = archive.CreateEntry(@"hoge\Test2.txt", CompressionLevel.Optimal);
                using (StreamWriter writer = new StreamWriter(entry.Open()))
                {
                    writer.WriteLine("FileContentSample-2");
                }
                
                // 既存のファイル(第一引数)を読み込んでzip内にファイルをつくる場合
                // archive.CreateEntryFromFile( @"C:\Test.txt", "a.txt", CompressionLevel.Optimal );
            }
        }
        catch(IOException e) {
            MessageBox.Show(e.ToString());
        }        
        catch(UnauthorizedAccessException e) {
            MessageBox.Show(e.ToString());
        }
    }
    
    [STAThread]
    static void Main(string[] args)
    {
        Application.Run(new ZipTest());
    }
}

フォルダからzipを作成する場合は

※zipにフォルダを追加するには、archive.CreateEntryFromFile で頑張るしかなさそう。

もう少し実用的なサンプル

指定された 1個のフォルダ または 複数のファイル(フォルダを含んではいけない)をzip化する。


using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.IO.Compression; // to use zip


class ZipMaker : Form
{

    static bool PreCheck(string[] args, out bool dirMode, out string errMsg)
    {
        errMsg = null;

        if (args.Length==1 && Directory.Exists(args[0]))
        {
            dirMode = true;
            return true;
        }
        else
        {
            dirMode = false;
            foreach (string arg in args)
            {
                if (!File.Exists(arg))
                {
                    if (Directory.Exists(arg))
                    {
                        errMsg = "This tool does not support multiple entries including folder. Only supports 1 folder, or files";
                    }
                    else
                    {
                        errMsg = "File not found: \"" + arg + "\"";
                    }
                    return false;
                }
            }
        }
        return true;
    }

    static void CreateZipFromFiles(string destZipPath, string[] files)
    {
        // https://stackoverflow.com/questions/15133626/creating-directories-in-a-ziparchive-c-sharp-net-4-5
        // https://docs.microsoft.com/ja-jp/dotnet/api/system.io.compression.ziparchive?view=netcore-3.1

        try
        {
            if (File.Exists(destZipPath))
            {
                // すでにファイルが存在する場合は削除する。
                File.Delete(destZipPath);
            }
            using( ZipArchive archive = ZipFile.Open(destZipPath, ZipArchiveMode.Create) )
            {
                foreach(string s in files)
                {
                    string path = Path.GetFullPath(s);
                    if (File.Exists(path))
                    {
                        archive.CreateEntryFromFile( path, Path.GetFileName(path), CompressionLevel.Optimal );
                    }
                    else
                    {
                        if (Directory.Exists(path))
                        {
                            Console.WriteLine("This tool does not support multiple entries including folder. Only supports 1 folder, or files");
                            Console.WriteLine("Ignored:\"" + path + "\"");
                        }
                        else
                        {
                            Console.WriteLine("File not found.");
                            Console.WriteLine("Ignored:\"" + path + "\"");
                        }
                    }
                }
            }
        }
        catch(IOException e)
        {
            MessageBox.Show(e.ToString());
        }        
        catch(UnauthorizedAccessException e)
        {
            MessageBox.Show(e.ToString());
        }
    }


    static string DestPathFromFileSaveAs(string defaultZipPath, string defaultZipName)
    {
        SaveFileDialog dlg = new SaveFileDialog();

        dlg.FileName = defaultZipName;
        dlg.InitialDirectory = defaultZipPath;
        dlg.Filter = "ZIP file(*.zip)|*.zip";
        dlg.FilterIndex = 1;
        dlg.Title = "Select file name to save";
        dlg.RestoreDirectory = true;
        dlg.OverwritePrompt = true;
        //dlg.CheckPathExists = true;

        if ( dlg.ShowDialog() == DialogResult.OK )
        {
            return dlg.FileName;
        }
        return null;
    }


    [STAThread]
    static void Main(string[] args)
    {
        bool dirMode;
        string errMsg;

        if (args.Length==0){return;}
        string path0 = Path.GetFullPath(args[0]);
        string parent0 = Path.GetDirectoryName(path0);
        
        if ( !PreCheck(args, out dirMode, out errMsg))
        {
            MessageBox.Show(errMsg);
        }

        string destPath;
        if (dirMode)
        {
            destPath = DestPathFromFileSaveAs(parent0, Path.GetFileName(path0) + ".zip");
            if(destPath!=null)
            {
                ZipFile.CreateFromDirectory(path0, destPath);// src folder, dest zip
            }
        }
        else
        {
            if (args.Length >= 2)
            {
                destPath = DestPathFromFileSaveAs(parent0, Path.GetFileName(parent0) + ".zip");
            }
            else
            {
                destPath = DestPathFromFileSaveAs(parent0, Path.GetFileName(path0) + ".zip");
            }

            if(destPath!=null)
            {
                CreateZipFromFiles(destPath, args);
            }
        }
    }
}

参考サイト

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2