HOME
  Security
   Software
    Hardware
  
FPGA
  CPU
   Android
    Raspberry Pi
  
nLite
  Xcode
   etc.
    ALL
  
English Translate 中文翻訳
LINK
BACK
 

[NEW] 2018/02/01

C#で ZIPファイル解凍ツール UnZipをソースリスト 1行で作る方法、Windows .NET専用 C#で ZIPファイル解凍ツール UnZipをソースリスト 1行で作る方法、Windows .NET専用

(Visual Studio 2013の C# .NET 4.5で ZipFile.ExtractToDirectoryを使い、UnZip解凍ツールを作成)

Tags: [Windows], [無人インストール]





● ZIPファイル解凍ツールをソースリスト 1行で作る方法

 Visual Studio 2013の C#で ZipFile.ExtractToDirectoryを使います。
ZipFile.ExtractToDirectory("ZIPファイルのパス", "解凍先ディレクトリ");
 以上!

 ZipFile クラス > ZipFile メソッド > ExtractToDirectory メソッド
ZipFile.ExtractToDirectory メソッド (String, String)
 指定した zip アーカイブのすべてのファイルをファイル システムのディレクトリに抽出します。
 名前空間: System.IO.Compression
 .NET Framework: 4.5以降で使用可能
 ※ Visual Studio 2012以降が必要


● Visual Studio 2013の練習で作成した ZIPファイル解凍専用アプリ

 Visual Studio 2013の練習で作成した ZIPファイル解凍専用アプリ。

UnZip.cs
using System.IO.Compression;

namespace UnZip
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2) return;

            string zipPath = args[0];
            string extractPath = args[1];

            ZipFile.ExtractToDirectory(zipPath, extractPath);
        }
    }
}
 ※ 解凍時に既にファイルが存在していると例外でアプリが落ちます。


●上書き対応の場合は ZipArchiveEntry.ExtractToFileを使用します。

ZipFileExtensions.ExtractToFile メソッド (ZipArchiveEntry, String, Boolean)

public static void ExtractToFile(
	this ZipArchiveEntry source,
	string destinationFileName,
	bool overwrite
)

パラメーター
source Type: System.IO.Compression.ZipArchiveEntry
ファイルを抽出する zip アーカイブ エントリ。

destinationFileName Type: System.String
エントリの内容から作成するファイルのパス。 相対パスと絶対パスのどちらかを指定することができます。 相対パスは、現在の作業ディレクトリに対して相対的に解釈されます。

overwrite Type: System.Boolean
宛先ファイルと同じ名前の既存のファイルを上書きする場合は true。それ以外の場合は false。

using System.IO;
using System.IO.Compression;

namespace UnZip
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2) return;

            string zipPath = args[0];
            string extractPath = args[1];
            bool overwrite = true;

            using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    // 完全なファイル名/ ディレクトリ名
                    String combineFilePath = Path.Combine(extractPath, entry.FullName);

                    // ディレクトリを作成する
                    if (entry.Name == "") {
                        CreateDirectory(combineFilePath);
                        continue;
                    }

                    // ディレクトリの有無を調べる
                    DirectoryInfo di = Directory.GetParent(combineFilePath);
                    if (!di.Exists)
                    {
                        CreateDirectory(di.FullName);
                    }

                    // ファイルを解凍する
                    entry.ExtractToFile(combineFilePath, overwrite);
                }
            }
        }

        static DirectoryInfo CreateDirectory(string path)
        {
            if (Directory.Exists(path))
            {
                return null;
            }

            return Directory.CreateDirectory(path);
        }
    }
}


●ついでに HTTPのファイルにも対応してみた版

 ZIPファイル名を指定した場合は ZIPファイルを解凍、
 http://~
 https://~
 ftp://~
 を指定した場合はインターネットから ZIPファイルをダウンロードしつつ解凍します。

 // Solution Explorer - Add Reference - Assemblies - Framework
 // System.IO.Compression
 // System.IO.Compression.FileSystem
 // .NET Framework 4.5以降で使用可能


using System;
using System.IO;
using System.IO.Compression;
using System.Net;

namespace UnZip
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2) return;

            string zipPath = args[0];
            string extractPath = args[1];
            bool overwrite = true;

            try
            {
                // 文字列の先頭を調べて Webかファイルかを切り替える
                if (zipPath.StartsWith("http") || zipPath.StartsWith("ftp"))
                {
                    DoWebRequest(zipPath, extractPath, overwrite);
                }
                else
                {
                    DoFileRequest(zipPath, extractPath, overwrite);
                }
            }
            catch (Exception e)
            {
                // 例外は全部キャッチして内容を表示する
                Console.WriteLine("Exception: " + e);
            }
        }


        // Webのファイルを ZIP解凍
        private static void DoWebRequest(string zipUrlPath, string extractPath, bool overwrite)
        {
            // Create a request for the URL.
            WebRequest request = WebRequest.Create(zipUrlPath);

            // Get the response.
            using (WebResponse response = request.GetResponse())
            {
                // Display the information.
                Console.WriteLine("ContentLength: " + response.ContentLength);
 //                Console.WriteLine("Headers: " + response.Headers);

                // Get the stream containing content returned by the server.
                using (Stream dataStream = response.GetResponseStream())
                {
                    using (ZipArchive archive = new ZipArchive(dataStream, ZipArchiveMode.Read))
                    {
                        ExtractZipArchive(archive, extractPath, overwrite);
                    }
                }
            }
        }


        // ファイルを ZIP解凍
        private static void DoFileRequest(string zipFilePath, string extractPath, bool overwrite)
        {
            FileInfo fi = new FileInfo(zipFilePath);
            // ファイルサイズを取得
            long fileSize = fi.Length;
            Console.WriteLine("FileSize: " + fileSize);

            using (ZipArchive archive = ZipFile.OpenRead(zipFilePath))
            {
                ExtractZipArchive(archive, extractPath, overwrite);
            }
        }


        // ZIP解凍の共通処理
        private static void ExtractZipArchive(ZipArchive archive, string extractPath, bool overwrite)
        {

#if false
            // ExtractToDirectory関数は上書き発生時に例外する
            archive.ExtractToDirectory(extractPath);

#else
            // ExtractToFile関数はファイル単位で処理をする
            long fileCount = 0L;
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                String fullName = entry.FullName;

                // NFD UTF-8-MAC対策
                if (!fullName.IsNormalized())
                {
                    fullName = fullName.Normalize();
                }

                // Mac避け "__MACOSX/"
                if (fullName.StartsWith("__MACOSX/"))
                {
                    continue;
                }
                // Mac避け ".DS_Store"
                if (fullName.EndsWith(".DS_Store"))
                {
                    continue;
                }


                // 完全なファイル名/ ディレクトリ名
                String combineFilePath = Path.Combine(extractPath, fullName);

                // ディレクトリを作成する
                if (entry.Name == "")
                {
                    CreateDirectory(combineFilePath);
                    continue;
                }

                // ディレクトリの有無を調べる
                DirectoryInfo di = Directory.GetParent(combineFilePath);
                if (!di.Exists)
                {
                    CreateDirectory(di.FullName);
                }

                // ファイルを解凍する
                entry.ExtractToFile(combineFilePath, overwrite);
                ++fileCount;
            }

            Console.WriteLine("Extracted: " + fileCount);
#endif
        }


        // ディレクトリの有無を調べて作成する
        private static DirectoryInfo CreateDirectory(string path)
        {
            if (Directory.Exists(path))
            {
                return null;
            }

            return Directory.CreateDirectory(path);
        }
    }
}


●エラー 1 型または名前空間名 'ZipArchive' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。

 「参照設定」で「参照の追加(R)...」で Compressで検索(絞込み)
System.IO.Compression
System.IO.Compression.FileSystem
 を追加する。

 .NET Framework: 4.5以降で使用可能
 ※ Visual Studio 2012以降が必要


● C#で NFDを NFCに変換する方法、MacOSの濁点や半濁点の文字が文字化けするのを対策

NFC Normalization Form Canonical Composition、正規化形式C
NFD Normalization Form Canonical Decomposition、正規化形式D

 Windowsでは NFCの「正規化形式C」、ガギグゲゴ
 ガ=U+30AC

 macOS OS Xでは NFDの「正規化形式D」、カ゛キ゛ク゛ケ゛コ゛
 カ゛=U+30AB、U+3099

● C#で macOS OS Xの UTF-8-MAC NFD形式を Windowsの UTF-8 NFC形式に変換する方法
var converted = "カ゚キ゚ク゚ケ゚コ゚".Normalize();

● C#で UTF-8の文字列が NFCかどうかを判定する方法
var isNfc = "ガギグゲゴ".IsNormalized(); // true ガ
var isNfc = "カ゚キ゚ク゚ケ゚コ゚".IsNormalized(); // false カ゛



● macOS Mac OS Xで作成した Zipファイルを Windowsで解凍する時の Mac避け

 NFD形式のファイル名を NFC形式に変換し、"__MACOSX"ディレクトリや ".DS_Store"ファイルを解凍しない様に無視します。
  foreach (ZipArchiveEntry entry in archive.Entries)
  {
    String fullName = entry.FullName;

    // NFD UTF-8-MAC対策
    if (!fullName.IsNormalized())
    {
        fullName = fullName.Normalize(); // NFD形式を NFC形式に変換
    }

    // Mac避け "__MACOSX/"
    if (fullName.StartsWith("__MACOSX/"))
    {
        continue;
    }
    // Mac避け ".DS_Store"
    if (fullName.EndsWith(".DS_Store"))
    {
        continue;
    }

    // 解凍処理を行なう
    ...

  }


● Visual Studio C#の未使用 usingの削除

 「編集(E)」>「IntelliSense(I)」>「usingの整理(O)」>「未使用の usingの削除(R)」

 ※ Javaで言う所の未使用の importの削除。




Tags: [Windows], [無人インストール]

●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)

Visual Studio 2013 Professionalを無人インストールする方法、完全自動でインストール
Visual Studio 2013 Professionalを無人インストールする方法、完全自動でインストール

  VS2013を Update 5適用済みとコンポーネント選択の事前設定でインストール時の手間を省く

Visual Studio 2015 Professionalを無人インストールする方法、完全自動でインストール
Visual Studio 2015 Professionalを無人インストールする方法、完全自動でインストール

  VS2015を Update 3適用済みとコンポーネント選択の事前設定でインストール時の手間を省く

Visual Studio 2017 Professionalを無人インストールする方法、完全自動でインストール
Visual Studio 2017 Professionalを無人インストールする方法、完全自動でインストール

  VS2017を完全オフラインインストール&コンポーネント選択の事前設定で自動インストールする



[HOME] | [BACK]
リンクフリー(連絡不要、ただしトップページ以外はweb構成の変更で移動する場合があります)
Copyright (c) 2018 FREE WING, Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator

http://www.neko.ne.jp/~freewing/software/visual_c_sharp_unzip_tool/