2013-03-23T00:33:38の更新内容

programming/netfx/stream/0_abstract/index.wiki.txt

current previous
1422,75 1422,6
 

        

        
 
Closeメソッドでストリームを閉じた後は、ほとんどのメソッドの呼び出しとプロパティの参照ができなくなります。 閉じたStreamに対してこれらの操作を行おうとすると例外&msdn(netfx,type,System.ObjectDisposedException){ObjectDisposedException};がスローされます。
Closeメソッドでストリームを閉じた後は、ほとんどのメソッドの呼び出しとプロパティの参照ができなくなります。 閉じたStreamに対してこれらの操作を行おうとすると例外&msdn(netfx,type,System.ObjectDisposedException){ObjectDisposedException};がスローされます。
 

        

        
+

          
+
***ベースとなるストリームのクローズ [#Stream_LeaveBaseStreamOpen]
+
[[GZipStream>programming/netfx/fcl/System.IO.Compression.GZipStream]]など他のストリームのラッパーとして動作するストリームの場合、そのストリームを閉じる際にベースとなったストリームも一緒に閉じるかどうかを指定することができるものがあります。 コンストラクタの引数&var{leaveOpen};にtrueを指定すると、Closeメソッドを呼び出したりusingステートメントから抜けてストリームを閉じた場合でも、ベースとなったストリームは開いたままになります。
+

          
+
次の例では、GZipStreamを使ってメモリ上で圧縮・展開を行なっていますが、圧縮と展開で同じMemoryStreamを使えるよう&var{leaveOpen};にtrueを指定してGZipStreamを作成しています。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.IO.Compression;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // GZipStreamで圧縮した結果を書き込むためのMemoryStreamを作成する
+
    using (Stream compressedStream = new MemoryStream()) {
+
      // データを圧縮してcompressedStreamに書き込むためのGZipStreamを作成する
+
      // (GZipStreamを閉じてもcompressedStreamは閉じないようleaveOpenをtrueにする)
+
      using (Stream gzipStream = new GZipStream(compressedStream, CompressionMode.Compress, true)) {
+
        // 圧縮するファイルのFileStreamを作成する
+
        using (Stream inputStream = File.OpenRead("sample.txt")) {
+
          // inputStreamからデータを読み出し、gzipStreamに書き込む
+
          inputStream.CopyTo(gzipStream);
+
        }
+
      }
+
      // この時点でgzipStreamは閉じられるが、compressedStreamは引き続き使用できる
+

          
+
      // compressedStreamの現在位置をストリームの先頭に戻し、GZipStreamで再度展開する
+
      compressedStream.Position = 0L;
+

          
+
      using (Stream gzipStream = new GZipStream(compressedStream, CompressionMode.Decompress, false)) {
+
        // StreamReaderを使って展開した内容を読み込んで表示する
+
        StreamReader reader = new StreamReader(gzipStream);
+

          
+
        Console.WriteLine(reader.ReadToEnd());
+
      }
+
      // この時点でgzipStreamは閉じられるが、leaveOpenにfalseを指定しているため、
+
      // compressedStreamも閉じられる
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Using fromStream As Stream = File.OpenRead("sample.dat")
+
      Using toStream As New MemoryStream()
+
        ' ファイルの内容をMemoryStreamにコピー
+
        fromStream.CopyTo(toStream)
+

          
+
        ' コピーした内容をバイト配列に変換して表示
+
        Console.WriteLine(BitConverter.ToString(toStream.ToArray()))
+
      End Using
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
なお、[[StreamReader・StreamWriter>programming/netfx/stream/2_streamreader_streamwriter#StreamReaderStreamWriter_CloseBaseStream]]や[[BinaryReader・BinaryWriter>programming/netfx/stream/3_binaryreader_binarywriter#BinaryReaderBinaryWriter_CloseBaseStream]]でもベースとなったストリームを開いたままにするかどうかを指定することができます。
+

          
+

          
+

          
 
**コピー (CopyTo) [#Stream.CopyTo]
**コピー (CopyTo) [#Stream.CopyTo]
 
ストリームの内容を別のストリームにコピーするには、&msdn(netfx,member,System.IO.Stream.CopyTo){CopyToメソッド};を使うことができます。 あるストリームの内容をコピーしてメモリ上(MemoryStream)に保持したり、ファイル(FileStream)に書き出したりしたい場合などに使えます。
ストリームの内容を別のストリームにコピーするには、&msdn(netfx,member,System.IO.Stream.CopyTo){CopyToメソッド};を使うことができます。 あるストリームの内容をコピーしてメモリ上(MemoryStream)に保持したり、ファイル(FileStream)に書き出したりしたい場合などに使えます。
 

        

        

programming/netfx/fcl/System.IO.Compression.ZipArchive/index.wiki.txt

current previous
1,637 0,0
+
${smdncms:title,System.IO.Compression.ZipArchive}
+
${smdncms:keywords,System.IO.Compression.ZipArchive,System.IO.Compression.dll,System.IO.Compression.ZipFile,System.IO.Compression.FileSystem.dll}
+
${smdncms:document_versions,codelang=cs,codelang=vb}
+

          
+
&msdn(netfx,type,System.IO.Compression.dll,System.IO.Compression.ZipArchive){ZipArchiveクラス};はZIPアーカイブの作成・展開・編集を行うためのクラス。 .NET Framework 4.5以降で使用することができる。 ZipArchiveクラスを使う場合は、System.IO.Compression.dllを参照に追加する必要がある。
+

          
+
-関連するページ
+
--[[programming/netfx/stream]]
+
--[[programming/netfx/fcl/System.IO.Compression.GZipStream]]
+

          
+
#googleadunit
+

          
+
*ZipArchiveクラス [#ZipArchive]
+
ZipArchiveクラスはインスタンスを作成する際に&msdn(netfx,type,System.IO.Stream){Stream};と&msdn(netfx,type,System.IO.Compression.dll,System.IO.Compression.ZipArchiveMode){ZipArchiveMode};を指定する。 ZipArchiveクラスでできる操作と動作は指定したZipArchiveModeによって次のように変わる。
+

          
+
|*ZipArchiveModeとZipArchiveクラスの動作
+
|~ZipArchiveMode|~ZipArchiveクラスの動作|h
+
|ZipArchiveMode.Read|StreamからZIPアーカイブを読み込み、展開する|
+
|ZipArchiveMode.Create|ZIPアーカイブを作成し、エントリを圧縮してStreamに書き込む|
+
|ZipArchiveMode.Update|ZipArchiveMode.ReadとZipArchiveMode.Createの操作の両方を行う&br;StreamからZIPアーカイブを読み込んで展開し、ZIPアーカイブの内容を変更した結果を再び圧縮してStreamに書き込む|
+

          
+
ZipArchiveクラスのコンストラクタでは、エントリ名(ZIPアーカイブ内のファイル名)で使用するエンコーディングを&msdn(netfx,type,System.Text.Encoding){Encoding};で指定することができる。
+

          
+
**ZIPアーカイブの展開 [#ZipArchive_Read]
+
ZipArchiveクラスを使ったZIPアーカイブの展開は次の順序で行う。
+

          
+
+ZIPアーカイブのStreamを開く
+
+開いたStreamとZipArchiveMode.Readを指定してZipArchiveを作成する
+
+&msdn(netfx,member,System.IO.Compression.dll,System.IO.Compression.ZipArchive.Entries){ZipArchive.Entriesプロパティ};もしくは&msdn(netfx,member,System.IO.Compression.dll,System.IO.Compression.ZipArchive.GetEntry){ZipArchive.GetEntryメソッド};で展開したいファイルの&msdn(netfx,type,System.IO.Compression.dll,System.IO.Compression.ZipArchiveEntry){ZipArchiveEntry};を取得する
+
+取得したZipArchiveEntryの&msdn(netfx,member,System.IO.Compression.dll,System.IO.Compression.ZipArchiveEntry.Open){Openメソッド};メソッドを呼び出してエントリのStreamを取得する
+
+取得したエントリのStreamから読み込むことで内容が展開される
+

          
+
次の例は、ZIPアーカイブを展開し、フォルダ構造を維持したまますべてのエントリを展開するもの。 なお、[[ZipFile.ExtractToDirectoryメソッド>#ZipFile.ExtractToDirectory]]を使うと、以下の例と同等のコードをメソッド呼び出し1つで実現できる。 また、ファイルへの展開には[[拡張メソッドExtractToFile>#ZipFileExtensions.ExtractToFile]]を使うこともできる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.IO.Compression;
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // ZIPアーカイブから展開したファイルを保存するディレクトリ
+
    const string extractDirectory = "extract";
+

          
+
    // sample.zipを開く
+
    using (var zipStream = File.OpenRead("sample.zip")) {
+
      // ストリームを読み込みZIPアーカイブを展開するためのZipArchiveを作成
+
      using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Read)) {
+
        // ZIPアーカイブ内の全エントリを列挙
+
        foreach (var entry in archive.Entries) {
+
          // エントリのアーカイブ内での相対パス名、サイズ、最終更新日を表示
+
          Console.Write("{0} ({1:N0} bytes, {2})", entry.FullName, entry.Length, entry.LastWriteTime);
+

          
+
          // エントリの展開先となるファイル名を作成
+
          var extractToFileName = Path.Combine(extractDirectory, entry.FullName);
+

          
+
          // サブディレクトリが存在しない場合は、先に作成しておく
+
          var extractToSubDirectory = Path.GetDirectoryName(extractToFileName);
+

          
+
          if (!Directory.Exists(extractToSubDirectory))
+
            Directory.CreateDirectory(extractToSubDirectory);
+

          
+
          // エントリを展開してファイルに保存する
+
          using (var entryStream = entry.Open()) {
+
            using (var extractToStream = File.Create(extractToFileName)) {
+
              entryStream.CopyTo(extractToStream);
+
            }
+
          }
+

          
+
          Console.WriteLine(" -> extracted to '{0}'", extractToFileName);
+
        }
+
      }
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.IO.Compression
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' ZIPアーカイブから展開したファイルを保存するディレクトリ
+
    Const extractDirectory As String = "extract"
+

          
+
    ' sample.zipを開く
+
    Using zipStream As Stream = File.OpenRead("sample.zip")
+
      ' ストリームを読み込みZIPアーカイブを展開するためのZipArchiveを作成
+
      Using archive As New ZipArchive(zipStream, ZipArchiveMode.Read)
+
        ' ZIPアーカイブ内の全エントリを列挙
+
        For Each entry As ZipArchiveEntry In archive.Entries
+
          ' エントリのアーカイブ内での相対パス名、サイズ、最終更新日を表示
+
          Console.Write("{0} ({1:N0} bytes, {2})", entry.FullName, entry.Length, entry.LastWriteTime)
+

          
+
          ' エントリの展開先となるファイル名を作成
+
          Dim extractToFileName As String = Path.Combine(extractDirectory, entry.FullName)
+

          
+
          ' サブディレクトリが存在しない場合は、先に作成しておく
+
          Dim extractToSubDirectory As String = Path.GetDirectoryName(extractToFileName)
+

          
+
          If Not Directory.Exists(extractToSubDirectory) Then Directory.CreateDirectory(extractToSubDirectory)
+

          
+
          ' エントリを展開してファイルに保存する
+
          Using entryStream As Stream = entry.Open()
+
            Using extractToStream As Stream = File.Create(extractToFileName)
+
              entryStream.CopyTo(extractToStream)
+
            End Using
+
          End Using
+

          
+
          Console.WriteLine(" -> extracted to '{0}'", extractToFileName)
+
        Next
+
      End Using
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果例){{
+
sample.txt (13 bytes, 2013/03/22 0:29:52 +09:00) -> extracted to 'extract\sample.txt'
+
サンプル.txt (21 bytes, 2013/03/22 0:29:52 +09:00) -> extracted to 'extract\サンプル.txt'
+
フォルダ1\a.txt (1,024 bytes, 2013/03/22 0:29:52 +09:00) -> extracted to 'extract\フォルダ1\a.txt'
+
フォルダ1\b.txt (1,024 bytes, 2013/03/22 0:29:52 +09:00) -> extracted to 'extract\フォルダ1\b.txt'
+
フォルダ1\c.txt (1,024 bytes, 2013/03/22 0:29:52 +09:00) -> extracted to 'extract\フォルダ1\c.txt'
+
}}
+

          
+
**ZIPアーカイブの作成 [#ZipArchive_Create]
+
ZipArchiveクラスを使ったZIPアーカイブの作成は次の順序で行う。
+

          
+
+ZIPアーカイブを書き込むためのStreamを開く
+
+開いたStreamとZipArchiveMode.Createを指定してZipArchiveを作成する
+
+&msdn(netfx,member,System.IO.Compression.dll,System.IO.Compression.ZipArchive.CreateEntry){ZipArchive.CreateEntryメソッド};でZipArchiveEntryを作成する
+
+作成したZipArchiveEntryの&msdn(netfx,member,System.IO.Compression.dll,System.IO.Compression.ZipArchiveEntry.Open){Openメソッド};メソッドを呼び出してエントリのStreamを取得する
+
+取得したエントリのStreamに書き込む事で圧縮して格納される
+

          
+
次の例は、フォルダ構造を維持したままフォルダ内のファイルを圧縮してZIPアーカイブを作成するもの。 なお、[[ZipFile.CreateFromDirectoryメソッド>#ZipFile.CreateFromDirectory]]を使うと、以下の例と同等のコードをメソッド呼び出し1つで実現できる。 また、ファイルからZipArchiveEntryを作成するには[[拡張メソッドCreateEntryFromFile>#ZipFileExtensions.CreateEntryFromFile]]を使うこともできる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.IO.Compression;
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // ZIPアーカイブとして圧縮したいファイルが存在するディレクトリ
+
    const string sourceDirectory = "source";
+

          
+
    // ZIPアーカイブとして圧縮するテスト用のファイルを用意する
+
    CreateTestFiles(sourceDirectory);
+

          
+
    // sample.zipを作成して開く
+
    using (var zipStream = File.Create("sample.zip")) {
+
      // ZIPアーカイブを作成してストリームに書き込むためのZipArchiveを作成
+
      using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create)) {
+
        // 相対パスを取得するために、ディレクトリのフルパスを区切り文字付きで取得しておく
+
        var directory = Path.GetFullPath(sourceDirectory) + Path.DirectorySeparatorChar;
+

          
+
        // ディレクトリ内にある全ての階層のファイルを列挙
+
        foreach (var file in Directory.EnumerateFiles(sourceDirectory, "*", SearchOption.AllDirectories)) {
+
          // エントリ名として使用するためにルートディレクトリからの相対パスを取得
+
          var entryName = Path.GetFullPath(file).Replace(directory, string.Empty);
+

          
+
          // エントリを作成
+
          var entry = archive.CreateEntry(entryName);
+

          
+
          // ファイルを開いてエントリに書き込む (圧縮する)
+
          using (var sourceStream = File.OpenRead(file)) {
+
            using (var entryStream = entry.Open()) {
+
              sourceStream.CopyTo(entryStream);
+
            }
+
          }
+

          
+
          Console.WriteLine("{0} -> {1}", file, entryName);
+
        }
+
      }
+
    }
+
  }
+

          
+
  private static void CreateTestFiles(string dir)
+
  {
+
    if (Directory.Exists(dir))
+
      Directory.Delete(dir, true);
+

          
+
    Directory.CreateDirectory(dir);
+

          
+
    File.WriteAllText(Path.Combine(dir, "sample.txt"), "Hello, world!");
+
    File.WriteAllText(Path.Combine(dir, "サンプル.txt"), "こんにちは世界");
+

          
+
    var subdir = Path.Combine(dir, "フォルダ1");
+

          
+
    Directory.CreateDirectory(subdir);
+

          
+
    File.WriteAllText(Path.Combine(subdir, "a.txt"), new string('a', 1024));
+
    File.WriteAllText(Path.Combine(subdir, "b.txt"), new string('b', 1024));
+
    File.WriteAllText(Path.Combine(subdir, "c.txt"), new string('c', 1024));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.IO.Compression
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' ZIPアーカイブとして圧縮したいファイルが存在するディレクトリ
+
    Const sourceDirectory As String = "source"
+

          
+
    ' ZIPアーカイブとして圧縮するテスト用のファイルを用意する
+
    CreateTestFiles(sourceDirectory)
+

          
+
    ' sample.zipを作成して開く
+
    Using zipStream As Stream = File.Create("sample.zip")
+
      ' ZIPアーカイブを作成してストリームに書き込むためのZipArchiveを作成
+
      Using archive As New ZipArchive(zipStream, ZipArchiveMode.Create)
+
        ' 相対パスを取得するために、ディレクトリのフルパスを区切り文字付きで取得しておく
+
        Dim dir As String = Path.GetFullPath(sourceDirectory) + Path.DirectorySeparatorChar
+

          
+
        ' ディレクトリ内にある全ての階層のファイルを列挙
+
        For Each f As String In Directory.EnumerateFiles(sourceDirectory, "*", SearchOption.AllDirectories)
+
          ' エントリ名として使用するためにルートディレクトリからの相対パスを取得
+
          Dim entryName As String = Path.GetFullPath(f).Replace(dir, String.Empty)
+

          
+
          ' エントリを作成
+
          Dim entry As ZipArchiveEntry = archive.CreateEntry(entryName)
+

          
+
          ' ファイルを開いてエントリに書き込む (圧縮する)
+
          Using sourceStream As Stream = File.OpenRead(f)
+
            Using entryStream As Stream = entry.Open()
+
              sourceStream.CopyTo(entryStream)
+
            End Using
+
          End Using
+

          
+
          Console.WriteLine("{0} -> {1}", f, entryName)
+
        Next
+
      End Using
+
    End Using
+
  End Sub
+

          
+
  Private Shared Sub CreateTestFiles(ByVal dir As String)
+
    If Not Directory.Exists(dir) Then Directory.Delete(dir, True)
+

          
+
    Directory.CreateDirectory(dir)
+

          
+
    File.WriteAllText(Path.Combine(dir, "sample.txt"), "Hello, world!")
+
    File.WriteAllText(Path.Combine(dir, "サンプル.txt"), "こんにちは世界")
+

          
+
    Dim subdir As String = Path.Combine(dir, "フォルダ1")
+

          
+
    Directory.CreateDirectory(subdir)
+

          
+
    File.WriteAllText(Path.Combine(subdir, "a.txt"), New String("a"c, 1024))
+
    File.WriteAllText(Path.Combine(subdir, "b.txt"), New String("b"c, 1024))
+
    File.WriteAllText(Path.Combine(subdir, "c.txt"), New String("c"c, 1024))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
source\sample.txt -> sample.txt
+
source\サンプル.txt -> サンプル.txt
+
source\フォルダ1\a.txt -> フォルダ1\a.txt
+
source\フォルダ1\b.txt -> フォルダ1\b.txt
+
source\フォルダ1\c.txt -> フォルダ1\c.txt
+
}}
+

          
+
***圧縮レベルの指定 [#CompressionLevel]
+
ZipArchive.CreateEntryメソッドでZipArchiveEntryを作成する際、同時に引数で圧縮レベルを指定することができる。 圧縮レベルの指定に使う&msdn(netfx,type,System.IO.Compression.CompressionLevel){CompressionLevel列挙体};の値には次のようなものがある。
+

          
+
|*CompressionLevel
+
|~CompressionLevel|~圧縮レベル|h
+
|CompressionLevel.Optimal|圧縮率優先|
+
|CompressionLevel.Fastest|圧縮速度優先|
+
|CompressionLevel.NoCompression|無圧縮|
+

          
+
**ZIPアーカイブの変更・更新 [#ZipArchive_Update]
+
ZipArchiveクラスを使ったZIPアーカイブの変更・更新は次の順序で行う。
+

          
+
+ZIPアーカイブを読み込むためのStreamを開く (このStreamは読み書き可能である必要がある)
+
+開いたStreamとZipArchiveMode.Updateを指定してZipArchiveを作成する
+
+[[ZIPアーカイブの作成の場合>#ZipArchive_Create]]と同様の手順でZipArchiveEntryを作成してファイルを追加する
+
+もしくは[[ZIPアーカイブの展開の場合>#ZipArchive_Read]]と同様の手順でZipArchiveEntryを取得し、&msdn(netfx,member,System.IO.Compression.dll,System.IO.Compression.ZipArchiveEntry.Delete){Deleteメソッド};で不要なエントリを削除する
+
+変更した内容はStreamに書き込まれてZIPアーカイブは更新される
+

          
+
次の例は、ZIPアーカイブを開いて、ZIPアーカイブ内に格納されているフォルダを削除するもの。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.IO.Compression;
+
using System.Linq;
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // 既存のZIPアーカイブsample.zipを開く
+
    using (var zipStream = File.Open("sample.zip", FileMode.Open)) {
+
      // ストリームを読み込みZIPアーカイブを変更・更新するためのZipArchiveを作成
+
      using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Update)) {
+
        // ZIPアーカイブ内の全エントリを列挙
+
        //   ZipArchiveEntry.Deleteメソッドでエントリを削除するとZipArchive.Entriesからも
+
        //   削除されるが、foreach内でDeleteすると列挙中にコレクションを変更することになる。
+
        //   そのため、ToArray()メソッドで配列に変換するなどして直接ZipArchive.Entriesの
+
        //   コレクションを列挙しないようにする。
+
        foreach (var entry in archive.Entries.ToArray()) {
+
          // エントリ名(相対パス)が"フォルダ1\"で始まるエントリを削除
+
          // (アーカイブ内のフォルダを削除する)
+
          if (entry.FullName.StartsWith("フォルダ1\\")) {
+
            entry.Delete();
+

          
+
            Console.WriteLine("deleted '{0}'", entry.FullName);
+
          }
+
        }
+
      }
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.IO.Compression
+
Imports System.Linq
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' 既存のZIPアーカイブsample.zipを開く
+
    Using zipStream As Stream = File.Open("sample.zip", FileMode.Open)
+
      ' ストリームを読み込みZIPアーカイブを変更・更新するためのZipArchiveを作成
+
      Using archive As New ZipArchive(zipStream, ZipArchiveMode.Update)
+
        ' ZIPアーカイブ内の全エントリを列挙
+
        '   ZipArchiveEntry.Deleteメソッドでエントリを削除するとZipArchive.Entriesからも
+
        '   削除されるが、foreach内でDeleteすると列挙中にコレクションを変更することになる。
+
        '   そのため、ToArray()メソッドで配列に変換するなどして直接ZipArchive.Entriesの
+
        '   コレクションを列挙しないようにする。
+
        For Each entry As ZipArchiveEntry In archive.Entries.ToArray()
+
          ' エントリ名(相対パス)が"フォルダ1\"で始まるエントリを削除
+
          ' (アーカイブ内のフォルダを削除する)
+
          If entry.FullName.StartsWith("フォルダ1\") Then
+
            entry.Delete()
+

          
+
            Console.WriteLine("deleted '{0}'", entry.FullName)
+
          End If
+
        Next
+
      End Using
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
deleted 'フォルダ1\a.txt'
+
deleted 'フォルダ1\b.txt'
+
deleted 'フォルダ1\c.txt'
+
}}
+

          
+
*ZipFileクラス [#ZipFile]
+
&msdn(netfx,type,System.IO.Compression.FileSystem.dll,System.IO.Compression.ZipFile){ZipFileクラス};には、ZIPアーカイブを扱う際によく行われる操作に対応するユーティリティメソッドが用意されている。 フォルダをまるごとZIPアーカイブとして圧縮したり、逆にZIPアーカイブをフォルダに展開するといった単純な操作は、ZipFileクラスのメソッドを呼び出すだけで行うことができる。
+

          
+
アセンブリ''System.IO.Compression.dll''に含まれるZipArchiveクラスに対して、ZipFileクラスは''System.IO.Compression.FileSystem.dll''に含まれるので、使う場合にはこのアセンブリも参照に含める必要がある。
+

          
+
**ZIPアーカイブの展開 [#ZipFile.ExtractToDirectory]
+
&msdn(netfx,member,System.IO.Compression.FileSystem.dll,System.IO.Compression.ZipFile.ExtractToDirectory){ZipFile.ExtractToDirectoryメソッド};を使うと、ZIPアーカイブを任意のフォルダに展開できる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
// csc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.cs
+
using System;
+
using System.IO.Compression;
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // sample.zipを展開し、展開したファイルをフォルダ"extract"以下に格納する
+
    ZipFile.ExtractToDirectory("sample.zip", "extract");
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
' vbc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.vb
+
Imports System
+
Imports System.IO.Compression
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' sample.zipを展開し、展開したファイルをフォルダ"extract"以下に格納する
+
    ZipFile.ExtractToDirectory("sample.zip", "extract")
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
[[上記の例と同等の動作をするコードをZipArchiveクラスを使って記述した例>#ZipArchive_Read]]
+

          
+
**ZIPアーカイブの作成 [#ZipFile.CreateFromDirectory]
+
&msdn(netfx,member,System.IO.Compression.FileSystem.dll,System.IO.Compression.ZipFile.CreateFromDirectory){ZipFile.CreateFromDirectoryメソッド};を使うと、指定したフォルダの内容を圧縮してZIPアーカイブを作成できる。
+

          
+
引数&var{includeBaseDirectory};にtrueを指定した場合、アーカイブされるファイルにはディレクトリ名も含まれる(フォルダ構造が維持される)。 falseを指定した場合は、ファイルのみとなる(フラットな構造でアーカイブされる)。 falseを指定した場合、既に同名のファイルがアーカイブ内に存在する場合はIOExceptionがスローされる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
// csc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.cs
+
using System;
+
using System.IO;
+
using System.IO.Compression;
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // ZIPアーカイブとして圧縮したいファイルが存在するディレクトリ
+
    const string sourceDirectory = "source";
+

          
+
    // ZIPアーカイブとして圧縮するテスト用のファイルを用意する
+
    CreateTestFiles(sourceDirectory);
+

          
+
    // フォルダ"source"のすべてのファイルを、フォルダ構造を維持したままsample.zipとして圧縮する
+
    ZipFile.CreateFromDirectory(sourceDirectory, "sample.zip", CompressionLevel.Fastest, true);
+
  }
+

          
+
  private static void CreateTestFiles(string dir)
+
  {
+
    if (Directory.Exists(dir))
+
      Directory.Delete(dir, true);
+

          
+
    Directory.CreateDirectory(dir);
+

          
+
    File.WriteAllText(Path.Combine(dir, "sample.txt"), "Hello, world!");
+
    File.WriteAllText(Path.Combine(dir, "サンプル.txt"), "こんにちは世界");
+

          
+
    var subdir = Path.Combine(dir, "フォルダ1");
+

          
+
    Directory.CreateDirectory(subdir);
+

          
+
    File.WriteAllText(Path.Combine(subdir, "a.txt"), new string('a', 1024));
+
    File.WriteAllText(Path.Combine(subdir, "b.txt"), new string('b', 1024));
+
    File.WriteAllText(Path.Combine(subdir, "c.txt"), new string('c', 1024));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
' vbc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.vb
+
Imports System
+
Imports System.IO
+
Imports System.IO.Compression
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' ZIPアーカイブとして圧縮したいファイルが存在するディレクトリ
+
    Const sourceDirectory As String = "source"
+

          
+
    ' ZIPアーカイブとして圧縮するテスト用のファイルを用意する
+
    CreateTestFiles(sourceDirectory)
+

          
+
    ' フォルダ"source"のすべてのファイルを、フォルダ構造を維持したままsample.zipとして圧縮する
+
    ZipFile.CreateFromDirectory(sourceDirectory, "sample.zip", CompressionLevel.Fastest, True)
+
  End Sub
+

          
+
  Private Shared Sub CreateTestFiles(ByVal dir As String)
+
    If Directory.Exists(dir) Then Directory.Delete(dir, True)
+

          
+
    Directory.CreateDirectory(dir)
+

          
+
    File.WriteAllText(Path.Combine(dir, "sample.txt"), "Hello, world!")
+
    File.WriteAllText(Path.Combine(dir, "サンプル.txt"), "こんにちは世界")
+

          
+
    Dim subdir As String = Path.Combine(dir, "フォルダ1")
+

          
+
    Directory.CreateDirectory(subdir)
+

          
+
    File.WriteAllText(Path.Combine(subdir, "a.txt"), New String("a"c, 1024))
+
    File.WriteAllText(Path.Combine(subdir, "b.txt"), New String("b"c, 1024))
+
    File.WriteAllText(Path.Combine(subdir, "c.txt"), New String("c"c, 1024))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
[[上記の例と同等の動作をするコードをZipArchiveクラスを使って記述した例>#ZipArchive_Create]]
+

          
+

          
+
*拡張メソッド [#ZipFileExtensions]
+
System.IO.Compression.FileSystem.dllを参照に追加すると、ZipArchiveクラスおよびZipArchiveEntryクラスに拡張メソッドが追加される。 拡張メソッドを使うことにより、ZIPアーカイブの操作をよりシンプルに記述できる。
+

          
+
**ExtractToDirectory [#ZipFileExtensions.ExtractToDirectory]
+
&msdn(netfx,member,System.IO.Compression.FileSystem.dll,System.IO.Compression.ZipFileExtensions.ExtractToDirectory){ExtractToDirectoryメソッド};はZipArchiveクラスに対して追加される拡張メソッドで、ZipArchiveに含まれるすべてのファイルを指定したフォルダに展開して保存する。  従って、ExtractToDirectoryは[[ZipFile.ExtractToDirectory>#ZipFile.ExtractToDirectory]]と同等の動作を行うメソッドとなる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
// csc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.cs
+
using System;
+
using System.IO.Compression;
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // sample.zipを開いてZIPアーカイブを展開するためのZipArchiveを作成
+
    using (var archive = ZipFile.Open("sample.zip", ZipArchiveMode.Read)) {
+
      // ZipArchiveからファイルを展開してフォルダ"extract"以下に格納する
+
      archive.ExtractToDirectory("extract");
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
' vbc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.vb
+
Imports System
+
Imports System.IO.Compression
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' sample.zipを開いてZIPアーカイブを展開するためのZipArchiveを作成
+
    Using archive As ZipArchive = ZipFile.Open("sample.zip", ZipArchiveMode.Read)
+
      ' ZipArchiveからファイルを展開してフォルダ"extract"以下に格納する
+
      archive.ExtractToDirectory("extract")
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
**ExtractToFile [#ZipFileExtensions.ExtractToFile]
+
&msdn(netfx,member,System.IO.Compression.FileSystem.dll,System.IO.Compression.ZipFileExtensions.ExtractToFile){ExtractToFileメソッド};はZipArchiveEntryクラス対して追加される拡張メソッドで、ZipArchiveEntryの内容を展開して指定したファイル名で保存することができる。 このメソッドは展開する際のファイル名を変更したり、個別に指定したりしたい場合などに使うことができる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
// csc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.cs
+
using System;
+
using System.IO.Compression;
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // sample.zipを開いてZIPアーカイブを展開するためのZipArchiveを作成
+
    using (var archive = ZipFile.Open("sample.zip", ZipArchiveMode.Read)) {
+
      // ZIPアーカイブ内の全エントリを列挙
+
      for (int index = 0; index < archive.Entries.Count; index++) {
+
        var entry = archive.Entries[index];
+

          
+
        // エントリを展開し、インデックスをファイル名に使用して保存
+
        entry.ExtractToFile(string.Format("{0}.tmp", index));
+
      }
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
' vbc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.vb
+
Imports System
+
Imports System.IO.Compression
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' sample.zipを開いてZIPアーカイブを展開するためのZipArchiveを作成
+
    Using archive As ZipArchive = ZipFile.Open("sample.zip", ZipArchiveMode.Read)
+
      ' ZIPアーカイブ内の全エントリを列挙
+
      For index As Integer = 0 To archive.Entries.Count - 1
+
        Dim entry As ZipArchiveEntry = archive.Entries(index)
+

          
+
        ' エントリを展開し、インデックスをファイル名に使用して保存
+
        entry.ExtractToFile(String.Format("{0}.tmp", index))
+
      Next
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
**CreateEntryFromFile [#ZipFileExtensions.CreateEntryFromFile]
+
&msdn(netfx,member,System.IO.Compression.FileSystem.dll,System.IO.Compression.ZipFileExtensions.CreateEntryFromFile){CreateEntryFromFileメソッド};はZipArchiveクラス対して追加される拡張メソッドで、指定したファイルの内容でZipArchiveEntryを作成し、ZipArchiveに追加することができる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
// csc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.cs
+
using System;
+
using System.IO.Compression;
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // ZIPアーカイブを作成してsample.zipに書き込むためのZipArchiveを作成
+
    using (var archive = ZipFile.Open("sample.zip", ZipArchiveMode.Update)) {
+
      // ファイル"a.txt"をエントリ名"1"でZipArchiveに追加
+
      var entry = archive.CreateEntryFromFile("a.txt", "1");
+

          
+
      // 追加したエントリの変更日時に別の値を設定
+
      // (ZipArchiveMode.CreateでZipArchiveを作成した場合は、プロパティを変更するとIOExceptionとなる)
+
      entry.LastWriteTime = new DateTimeOffset(2000, 1, 23, 4, 56, 7, new TimeSpan(8, 0, 0));
+

          
+
      // さらに別のファイルをZipArchiveに追加
+
      archive.CreateEntryFromFile("b.txt", "2");
+
      archive.CreateEntryFromFile("c.txt", "3");
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
' vbc /r:System.IO.Compression.dll /r:System.IO.Compression.FileSystem.dll Sample.vb
+
Imports System
+
Imports System.IO.Compression
+

          
+
Class Sample
+
  Shared Sub Main()
+
    ' ZIPアーカイブを作成してsample.zipに書き込むためのZipArchiveを作成
+
    Using archive As ZipArchive = ZipFile.Open("sample.zip", ZipArchiveMode.Update)
+
      ' ファイル"a.txt"をエントリ名"1"でZipArchiveに追加
+
      Dim entry As ZipArchiveEntry = archive.CreateEntryFromFile("a.txt", "1")
+

          
+
      ' 追加したエントリの変更日時に別の値を設定
+
      ' (ZipArchiveMode.CreateでZipArchiveを作成した場合は、プロパティを変更するとIOExceptionとなる)
+
      entry.LastWriteTime = New DateTimeOffset(2000, 1, 23, 4, 56, 7, New TimeSpan(8, 0, 0))
+

          
+
      ' さらに別のファイルをZipArchiveに追加
+
      archive.CreateEntryFromFile("b.txt", "2")
+
      archive.CreateEntryFromFile("c.txt", "3")
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+

          

programming/netfx/fcl/System.IO.Compression.GZipStream/index.wiki.txt

current previous
1,22 1,18
 
${smdncms:title,System.IO.Compression.GZipStream}
${smdncms:title,System.IO.Compression.GZipStream}
 
${smdncms:keywords,System.IO.Compression,GZipStream}
${smdncms:keywords,System.IO.Compression,GZipStream}
+
${smdncms:document_versions,codelang=cs,codelang=vb}
 

        

        
~
&msdn(netfx,type,System.IO.Compression.GZipStream){GZipStream};はgzip形式の圧縮・展開(伸張)を行うためのストリーム。 .NET Frameworkでは&msdn(netfx,type,System.Net.HttpWebResponse){HttpWebResponseクラス};がgzipで圧縮されたコンテンツ(Content-Encoding: gzip)を展開する場合にGZipStreamを使用するが、ファイルの圧縮などにも利用することができる。
GZipStreamはgzip形式の圧縮・展開(伸張)を行うためのストリーム。 HTTPなどでデータを圧縮して送信する場合などに使用する。 圧縮と展開のどちらにも対応しているが、インスタンス生成時に圧縮用か展開用かどちらか一方を指定する必要がある。 このストリームに対して書き込み・読み込みを行うことにより、圧縮・展開することができる。
 

        

        
~
GZipStreamは圧縮と展開のどちらにも対応しているが、インスタンス生成時に圧縮用か展開用かどちらか一方を指定する必要がある。 このストリームに対して書き込み・読み込みを行うことにより、gzip形式での圧縮・展開することができる。
類似のクラスとして、LZ77形式の圧縮・展開を行うためのDeflateStreamというクラスもある。 gzip形式・LZ77形式のいずれも可逆圧縮なので、当然圧縮前と展開後のデータのサイズは同じになる。
+

          
+
類似のクラスとして、LZ77形式の圧縮・展開を行うための&msdn(netfx,type,System.IO.Compression.DeflateStream){DeflateStream};というクラスもある。 gzip形式・LZ77形式のいずれも可逆圧縮なので、当然圧縮前と展開後のデータのサイズは同じになる。
 

        

        
 
-関連するページ
-関連するページ
 
--[[programming/netfx/stream]]
--[[programming/netfx/stream]]
+
--[[programming/netfx/fcl/System.IO.Compression.ZipArchive]]
 

        

        
 
#googleadunit
#googleadunit
 

        

        
 
*主なコンストラクタ
*主なコンストラクタ
 
:GZipStream(Stream, CompressionMode)|圧縮・展開を行う対象のストリーム、圧縮か展開のどちらの操作を行うか指定してインスタンスを生成する。 圧縮用にストリームを作成する場合はCompressionMode.Compress、展開用にストリームを作成する場合はCompressionMode.Decompressを指定する。
:GZipStream(Stream, CompressionMode)|圧縮・展開を行う対象のストリーム、圧縮か展開のどちらの操作を行うか指定してインスタンスを生成する。 圧縮用にストリームを作成する場合はCompressionMode.Compress、展開用にストリームを作成する場合はCompressionMode.Decompressを指定する。
~
:GZipStream(Stream, CompressionMode, Boolean)|[[圧縮/展開が終わってCloseしたあともストリームを開いたままにするかどうか>programming/netfx/stream/0_abstract#Stream_LeaveBaseStreamOpen]]を指定してインスタンスを生成する。 Trueを指定すると、GZipStreamを閉じてもベースとなるストリームは開かれたままになるので、圧縮・展開したストリームを使って追加の処理を行えるようストリームを再利用することができる。
:GZipStream(Stream, CompressionMode, Boolean)|圧縮/展開が終わってCloseしたあともストリームを開いたままにするかどうか指定してインスタンスを生成する。 Trueを指定すると、ストリームは開かれたままになるので、追記などを行うためにストリームを再利用することができる。
 

        

        
 
*主なメソッド
*主なメソッド
 
:void Write(byte[], int, int)|指定したバイト配列を圧縮し、ストリームに書き込む。
:void Write(byte[], int, int)|指定したバイト配列を圧縮し、ストリームに書き込む。
34,272 30,82
 
+Close()
+Close()
 

        

        
 
*使用例
*使用例
~
GZipStreamを使ってテキストファイルの内容を圧縮して別のファイルに保存する。 また、圧縮したファイルを再び展開して別のファイルに保存する。 この例で使用している[[Stream.CopyTo>programming/netfx/stream/0_abstract#Stream.CopyTo]]メソッドは.NET Framework 4以降でないと使用できないので注意。
GZipStreamを使ってテキストファイルの内容を圧縮し、圧縮したものを再び展開する。
-

          
-
#googleadunit
 

        

        
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.IO.Compression;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine("[Compression]");
+

          
+
    // 圧縮するファイルのFileStreamを作成する
+
    using (var inputStream = File.OpenRead("sample.txt")) {
+
      // 圧縮した結果を保存するファイルのFileStreamを作成する
+
      using (var outputStream = File.Create("sample.txt.gz")) {
+
        // データを圧縮してoutputStreamに書き込むためのGZipStreamを作成する
+
        // (GZipStreamを閉じた後でもoutputStream.Lengthを参照できるよう、leaveOpenはtrueにする)
+
        using (var gzipStream = new GZipStream(outputStream, CompressionMode.Compress, true)) {
+
#if STREAM_COPY
+
          // inputStreamからデータを読み出し、gzipStreamに書き込む
+
          inputStream.CopyTo(gzipStream);
+
#else
+
          // .NET Framework 4より前のバージョンではCopyToメソッドを使うことはできないので以下のようにする
+
          var buffer = new byte[1024];
+

          
+
          for (;;) {
+
            var len = inputStream.Read(buffer, 0, buffer.Length);
+

          
+
            if (len == 0)
+
              break;
+

          
+
            gzipStream.Write(buffer, 0, len);
+
          }
+
#endif
+
        }
+

          
+
        // 圧縮前後のファイルサイズを表示
+
        Console.WriteLine("original: {0:N0} bytes", inputStream.Length);
+
        Console.WriteLine("compressed: {0:N0} bytes ({1:P1})",
+
                          outputStream.Length, outputStream.Length / (double)inputStream.Length);
+
      }
+
    }
+

          
+
    Console.WriteLine("[Decompression]");
+

          
+
    // 展開するファイルのFileStreamを作成する
+
    using (var inputStream = File.OpenRead("sample.txt.gz")) {
+
      // inputStreamから読み込みデータを展開するためのGZipStreamを作成する
+
      // (GZipStreamを閉じた後でもinputStream.Lengthを参照できるよう、leaveOpenはtrueにする)
+
      using (var gzipStream = new GZipStream(inputStream, CompressionMode.Decompress, true)) {
+
        // 展開した結果を保存するファイルのFileStreamを作成する
+
        using (var outputStream = File.Create("out.txt")) {
+
#if STREAM_COPY
+
          // gzipStreamから展開されたデータを読み出し、outputStreamに書き込む
+
          gzipStream.CopyTo(outputStream);
+
#else
+
          // .NET Framework 4より前のバージョンではCopyToメソッドを使うことはできないので以下のようにする
+
          var buffer = new byte[1024];
+

          
+
          for (;;) {
+
            var len = gzipStream.Read(buffer, 0, buffer.Length);
+

          
+
            if (len == 0)
+
              break;
+

          
+
            outputStream.Write(buffer, 0, len);
+
          }
+
#endif
+

          
+
          // 展開前後のファイルサイズを表示
+
          Console.WriteLine("original: {0:N0} bytes", inputStream.Length);
+
          Console.WriteLine("decompressed: {0:N0} bytes ({1:P1})",
+
                            outputStream.Length, outputStream.Length / (double)inputStream.Length);
+
        }
+
      }
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
 
#code(vb){{
#code(vb){{
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
 
Imports System.IO.Compression
Imports System.IO.Compression
-
Imports Microsoft.VisualBasic.FileIO
-

          
-
Class CompressionSample
-

          
-
  Public Shared Function Main() As Integer
-

          
-
    Dim dataStream As MemoryStream = Nothing
-
    Dim gzipStream As GZipStream = Nothing
-
    Dim originalBytes As Byte() = FileSystem.ReadAllBytes( "sample.txt" )
-

          
-
    Console.WriteLine( "Original size: {0:N0}", originalBytes.Length )
-

          
-
    ' 圧縮
-
    dataStream = New MemoryStream()
-

          
-
    gzipStream = New GZipStream( dataStream, CompressionMode.Compress, True )
-

          
-
    gzipStream.Write( originalBytes, 0, originalBytes.Length )
-

          
-
    Console.WriteLine( "Compressed size: {0:N0}", dataStream.Length )
-

          
-
    gzipStream.Close()
-

          
-
    gzipStream = Nothing
-

          
-
    ' 展開
-
    dataStream.Position = 0
 

        

        
~
Class Sample
    gzipStream = New GZipStream( dataStream, CompressionMode.Decompress )
~
  Shared Sub Main()

          
~
    Console.WriteLine("[Compression]")
    Dim buffer(256 - 1) As Byte
~

          
    Dim read As Integer = 0
~
    ' 圧縮するファイルのFileStreamを作成する
    Dim len As Integer
~
    Using inputStream As  FileStream = File.OpenRead("sample.txt")

          
~
      ' 圧縮した結果を保存するファイルのFileStreamを作成する
    Do
~
      Using outputStream As FileStream = File.Create("sample.txt.gz")

          
~
        ' データを圧縮してoutputStreamに書き込むためのGZipStreamを作成する
      len = gzipStream.Read( buffer, 0, buffer.Length )
+
        ' (GZipStreamを閉じた後でもoutputStream.Lengthを参照できるよう、leaveOpenはtrueにする)
+
        Using gzipStream As New GZipStream(outputStream, CompressionMode.Compress, True)
+
#If STREAM_COPY
+
          ' inputStreamからデータを読み出し、gzipStreamに書き込む
+
          inputStream.CopyTo(gzipStream)
+
#Else
+
          ' .NET Framework 4より前のバージョンではCopyToメソッドを使うことはできないので以下のようにする
+
          Dim buffer(1024 - 1) As Byte
+

          
+
          Do
+
            Dim len As Integer = inputStream.Read(buffer, 0, buffer.Length)
+

          
+
            If len = 0 Then Exit Do
+

          
+
            gzipStream.Write(buffer, 0, len)
+
          Loop
+
#End If
+
        End Using
+

          
+
        ' 圧縮前後のファイルサイズを表示
+
        Console.WriteLine("original: {0:N0} bytes", inputStream.Length)
+
        Console.WriteLine("compressed: {0:N0} bytes ({1:P1})", _
+
                          outputStream.Length, outputStream.Length / inputStream.Length)
+
      End Using
+
    End Using
+

          
+
    Console.WriteLine("[Decompression]")
+

          
+
    ' 展開するファイルのFileStreamを作成する
+
    Using inputStream As FileStream = File.OpenRead("sample.txt.gz")
+
      ' inputStreamから読み込みデータを展開するためのGZipStreamを作成する
+
      ' (GZipStreamを閉じた後でもinputStream.Lengthを参照できるよう、leaveOpenはtrueにする)
+
      Using gzipStream As New GZipStream(inputStream, CompressionMode.Decompress, true)
+
        ' 展開した結果を保存するファイルのFileStreamを作成する
+
        Using outputStream As FileStream = File.Create("out.txt")
+
#If STREAM_COPY
+
          ' gzipStreamから展開されたデータを読み出し、outputStreamに書き込む
+
          gzipStream.CopyTo(outputStream)
+
#Else
+
          ' .NET Framework 4より前のバージョンではCopyToメソッドを使うことはできないので以下のようにする
+
          Dim buffer(1024 - 1) As Byte
+

          
+
          Do
+
            Dim len As Integer = gzipStream.Read(buffer, 0, buffer.Length)
+

          
+
            If len = 0 Then Exit Do
+

          
+
            outputStream.Write(buffer, 0, len)
+
          Loop
+
#End If
+

          
+
          ' 展開前後のファイルサイズを表示
+
          Console.WriteLine("original: {0:N0} bytes", inputStream.Length)
+
          Console.WriteLine("decompressed: {0:N0} bytes ({1:P1})", _
+
                            outputStream.Length, outputStream.Length / inputStream.Length)
+
        End Using
+
      End Using
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt(.NET Framework 4での実行結果例){{
      If len = 0 Then Exit Do
+
[Compression]
+
original: 3,208 bytes
+
compressed: 941 bytes (29.3%)
+
[Decompression]
+
original: 941 bytes
+
decompressed: 3,208 bytes (340.9%)
+
}}
 

        

        
~
#prompt(Mono 2.10.8での実行結果例){{
      read += len
+
[Compression]
+
original: 3,208 bytes
+
compressed: 941 bytes (29.3%)
+
[Decompression]
+
original: 941 bytes
+
decompressed: 3,208 bytes (340.9%)
+
}}
 

        

        
~
同じ内容のファイルについて、GZipStreamの代わりにDeflateStreamを使用して実行した例。
    Loop
 

        

        
~
#prompt(.NET Framework 4での実行結果例){{
    gzipStream.Close()
+
[Compression]
+
original: 3,208 bytes
+
compressed: 923 bytes (28.8%)
+
[Decompression]
+
original: 923 bytes
+
decompressed: 3,208 bytes (347.6%)
+
}}
 

        

        
~
#prompt(Mono 2.10.8での実行結果例){{
    Console.WriteLine( "Decompressed size: {0:N0}", read )
+
[Compression]
+
original: 3,208 bytes
+
compressed: 923 bytes (28.8%)
+
[Decompression]
+
original: 923 bytes
+
decompressed: 3,208 bytes (347.6%)
+
}}
 

        

        
~
*圧縮レベルの指定
    Return 0
+
.NET Framework 4.5からは、GZipStream・DeflateStreamのコンストラクタに&msdn(netfx,type,System.IO.Compression.CompressionLevel){CompressionLevel列挙体};の値を指定できるようになっている。 これにより圧縮時の圧縮レベルを指定することができる。 GZipStream・DeflateStreamに指定できる圧縮レベルは次のとおり。
 

        

        
~
|*CompressionLevel
  End Function
+
|~CompressionLevel|~圧縮レベル|h
+
|CompressionLevel.Optimal|圧縮率優先|
+
|CompressionLevel.Fastest|圧縮速度優先|
+
|CompressionLevel.NoCompression|無圧縮|
+

          
+
GZipStreamにCompressionLevelを指定して圧縮した場合の所要時間、圧縮率の違いは次の通り。
+

          
+
#prompt(Windows 7 + .NET Framework 4.5での実行結果例){{
+
E:\>sample.exe sample.dat
+
input length: 681836
+
Optimal        : 00:00:00.0433742 14.3%
+
Fastest        : 00:00:00.0179198 16.7%
+
NoCompression  : 00:00:00.0104490 100.0%
+

          
+
E:\>sample.exe sample.txt
+
input length: 3208
+
Optimal        : 00:00:00.0010596 29.3%
+
Fastest        : 00:00:00.0002112 31.3%
+
NoCompression  : 00:00:00.0001500 100.7%
+

          
+
E:\>sample.exe sample.avi
+
input length: 76800512
+
Optimal        : 00:00:07.3913581 43.2%
+
Fastest        : 00:00:03.4181816 47.2%
+
NoCompression  : 00:00:01.1296466 100.0%
 

        

        
-
End Class
 
}}
}}
 

        

        
~
#code(cs,検証に使ったコード){{
実行例。
~
using System;

          
~
using System.IO;
#prompt{{
~
using System.IO.Compression;
Original size: 13,060
~
using System.Diagnostics;
Compressed size: 2,752
~

          
Decompressed size: 13,060
+
class Sample
+
{
+
  static void Main(string[] args)
+
  {
+
    using (var inputStream = File.OpenRead(args[0])) {
+
      Console.WriteLine("input length: {0}", inputStream.Length);
+

          
+
      // CompressionLevelの値を列挙
+
      foreach (CompressionLevel compressionLevel in Enum.GetValues(typeof(CompressionLevel))) {
+
        Console.Write("{0,-15}: ", compressionLevel);
+

          
+
        // 初期サイズに元ファイルのサイズ分を確保してMemoryStreamを作成
+
        using (var outputStream = new MemoryStream((int)inputStream.Length)) {
+
          using (var gzipStream = new GZipStream(outputStream, compressionLevel, true)) {
+
            var sw = Stopwatch.StartNew();
+

          
+
            inputStream.Position = 0L;
+
            inputStream.CopyTo(gzipStream);
+

          
+
            // 圧縮にかかった時間を表示
+
            Console.Write("{0} ", sw.Elapsed);
+
          }
+

          
+
          // 圧縮率を表示
+
          Console.WriteLine("{0:P1}", outputStream.Length / (double)inputStream.Length);
+
        }
+
      }
+
    }
+
  }
+
}
 
}}
}}
 

        

        
-
同じ内容のファイルについて、GZipStreamの代わりにDeflateStreamを使用して実行した例。
-

          
-
#prompt{{
-
Original size: 13,060
-
Compressed size: 2,742
-
Decompressed size: 13,060
-
}}
 

        

        

programming/netfx/tips/set_volume_of_soundplayer/index.wiki.txt

current previous
1,466 0,0
+
${smdncms:title,SoundPlayerで再生される音声の音量を変更する}
+
${smdncms:keywords,C#,VB.NET,System.Media.SoundPlayer,WAVE,音量,再生,ボリューム,変更}
+
${smdncms:tags,plat/win,api/win32,api/.net,lang/c#,lang/vb}
+
${smdncms:document_versions,codelang=cs,codelang=vb}
+

          
+
&msdn(netfx,type,System.Media.SoundPlayer){SoundPlayerクラス};には再生される音声のボリュームを設定・変更するプロパティやメソッドが用意されていない。 一方、SoundPlayerは任意のStreamから音声を読み込み再生することができる。 そこで、音声の読み込みと同時にボリュームの変更を行うようにした&msdn(netfx,type,System.IO.Stream){Stream};を作成し、それを音声ソースとしてSoundPlayerに渡すことによってボリュームを変更する。
+

          
+
-関連するページ
+
--[[programming/netfx/tips/wave_playsound]]
+
--[[programming/netfx/tips/wave_volume_curve]]
+
--[[programming/netfx/stream]]
+
---[[programming/netfx/stream/0_abstract]]
+
---[[programming/netfx/stream/3_binaryreader_binarywriter]]
+

          
+
#googleadunit
+

          
+
*実装例
+
以下のコードでは、WAVE形式のデータを読み込むクラスWaveStreamを作成し、それをSoundPlayerのコンストラクタに渡している。 WaveStreamのReadメソッドを呼び出すと、読み込んだWAVEデータのヘッダ部分はそのまま返すが、dataチャンク内の各音声サンプルについては音量を変更した上で返すように実装している。 元の音声より大きい音量にすることはできない。
+

          
+
なお、以下のコードにおけるWaveStreamクラスは16ビットのWAVE形式の音声のみに対応している。 モノラル・ステレオなど、チャンネル数は任意のものに対応している。 また、RIFFヘッダのチェック等は省略しているので、ヘッダの内容によっては予期しない動作となる可能性もある。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Media;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    const string waveFile = "test.wav";
+

          
+
    using (var stream = new WaveStream(File.OpenRead(waveFile))) {
+
      // 0 から 100の範囲で音量を指定する
+
      stream.Volume = 75;
+

          
+
      // WaveStreamから音声を読み込みSoundPlayer.PlaySyncメソッドで再生
+
      using (var player = new SoundPlayer(stream)) {
+
        player.PlaySync();
+
      }
+
    }
+
  }
+
}
+

          
+
class WaveStream : Stream {
+
  public override bool CanSeek {
+
    // シークはサポートしない
+
    get { return false; }
+
  }
+

          
+
  public override bool CanRead {
+
    get { return !IsClosed; }
+
  }
+

          
+
  public override bool CanWrite {
+
    // 書き込みはサポートしない
+
    get { return false; }
+
  }
+

          
+
  private bool IsClosed {
+
    get { return reader == null; }
+
  }
+

          
+
  public override long Position {
+
    get { CheckDisposed(); throw new NotSupportedException(); }
+
    set { CheckDisposed(); throw new NotSupportedException(); }
+
  }
+

          
+
  public override long Length {
+
    get { CheckDisposed(); throw new NotSupportedException(); }
+
  }
+

          
+
  public int Volume {
+
    get { CheckDisposed(); return volume; }
+
    set {
+
      CheckDisposed();
+

          
+
      if (value < 0 || MaxVolume < value)
+
        throw new ArgumentOutOfRangeException("Volume",
+
                                              value,
+
                                              string.Format("0から{0}の範囲の値を指定してください", MaxVolume));
+

          
+
      volume = value;
+
    }
+
  }
+

          
+
  public WaveStream(Stream baseStream)
+
  {
+
    if (baseStream == null)
+
      throw new ArgumentNullException("baseStream");
+
    if (!baseStream.CanRead)
+
      throw new ArgumentException("読み込み可能なストリームを指定してください", "baseStream");
+

          
+
    this.reader = new BinaryReader(baseStream);
+

          
+
    ReadHeader();
+
  }
+

          
+
  public override void Close()
+
  {
+
    if (reader != null) {
+
      reader.Close();
+
      reader = null;
+
    }
+
  }
+

          
+
  // dataチャンクまでのヘッダブロックの内容をバッファに読み込んでおく
+
  // WAVEFORMAT等のヘッダ内容のチェックは省略
+
  private void ReadHeader()
+
  {
+
    using (var headerStream = new MemoryStream()) {
+
      var writer = new BinaryWriter(headerStream);
+

          
+
      // RIFFヘッダ
+
      var riffHeader = reader.ReadBytes(12);
+

          
+
      writer.Write(riffHeader);
+

          
+
      // dataチャンクまでの内容をwriterに書き写す
+
      for (;;) {
+
        var chunkHeader = reader.ReadBytes(8);
+

          
+
        writer.Write(chunkHeader);
+

          
+
        var fourcc = BitConverter.ToInt32(chunkHeader, 0);
+
        var size = BitConverter.ToInt32(chunkHeader, 4);
+

          
+
        if (fourcc == 0x61746164) // 'data'
+
          break;
+

          
+
        writer.Write(reader.ReadBytes(size));
+
      }
+

          
+
      writer.Close();
+

          
+
      header = headerStream.ToArray();
+
    }
+
  }
+

          
+
  public override int Read(byte[] buffer, int offset, int count)
+
  {
+
    CheckDisposed();
+

          
+
    if (buffer == null)
+
      throw new ArgumentNullException("buffer");
+
    if (offset < 0)
+
      throw new ArgumentOutOfRangeException("offset", offset, "0以上の値を指定してください");
+
    if (count < 0)
+
      throw new ArgumentOutOfRangeException("count", count, "0以上の値を指定してください");
+
    if (buffer.Length - count < offset)
+
      throw new ArgumentException("配列の範囲を超えてアクセスしようとしました", "offset");
+

          
+
    if (header == null) {
+
      // dataチャンクの読み込み
+
      // WAVEサンプルを読み込み、音量を適用して返す
+
      // ストリームは16ビット(1サンプル2バイト)と仮定
+

          
+
      // countバイト以下となるよう読み込むサンプル数を決定する
+
      var samplesToRead = count / 2;
+
      var bytesToRead = samplesToRead * 2;
+
      var len = reader.Read(buffer, offset, bytesToRead);
+

          
+
      if (len == 0)
+
        return 0; // 終端まで読み込んだ
+

          
+
      // 読み込んだサンプル1つずつにボリュームを適用する
+
      for (var sample = 0; sample < samplesToRead; sample++) {
+
        short s = (short)(buffer[offset] | (buffer[offset + 1] << 8));
+

          
+
        s = (short)(((int)s * volume) / MaxVolume);
+

          
+
        buffer[offset] = (byte)(s & 0xff);
+
        buffer[offset + 1] = (byte)((s >> 8) & 0xff);
+

          
+
        offset += 2;
+
      }
+

          
+
      return len;
+
    }
+
    else {
+
      // ヘッダブロックの読み込み
+
      // バッファに読み込んでおいた内容をそのままコピーする
+
      var bytesToRead = Math.Min(header.Length - headerOffset, count);
+

          
+
      Buffer.BlockCopy(header, headerOffset, buffer, offset, bytesToRead);
+

          
+
      headerOffset += bytesToRead;
+

          
+
      if (headerOffset == header.Length)
+
        // ヘッダブロックを全て読み込んだ
+
        // (不要になったヘッダのバッファを解放し、以降はdataチャンクの読み込みに移る)
+
        header = null;
+

          
+
      return bytesToRead;
+
    }
+
  }
+

          
+
  public override void SetLength(long @value)
+
  {
+
    CheckDisposed();
+

          
+
    throw new NotSupportedException();
+
  }
+

          
+
  public override long Seek(long offset, SeekOrigin origin)
+
  {
+
    CheckDisposed();
+

          
+
    throw new NotSupportedException();
+
  }
+

          
+
  public override void Flush()
+
  {
+
    CheckDisposed();
+

          
+
    throw new NotSupportedException();
+
  }
+

          
+
  public override void Write(byte[] buffer, int offset, int count)
+
  {
+
    CheckDisposed();
+

          
+
    throw new NotSupportedException();
+
  }
+

          
+
  private void CheckDisposed()
+
  {
+
    if (IsClosed)
+
      throw new ObjectDisposedException(GetType().FullName);
+
  }
+

          
+
  private BinaryReader reader;
+
  private byte[] header;
+
  private int headerOffset = 0;
+
  private int volume = MaxVolume;
+
  private const int MaxVolume = 100;
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.Media
+

          
+
Class Sample
+
  Shared Sub Main()
+
    Const waveFile As String = "test.wav"
+

          
+
    Using stream As New WaveStream(File.OpenRead(waveFile))
+
      ' 0 から 100の範囲で音量を指定
+
      stream.Volume = 75
+

          
+
      ' WaveStreamから音声を読み込みSoundPlayer.PlaySyncメソッドで再生
+
      Using player As New SoundPlayer(stream)
+
        player.PlaySync()
+
      End Using
+
    End Using
+
  End Sub
+
End Class
+

          
+
Class WaveStream
+
  Inherits Stream
+

          
+
  Public Overrides ReadOnly Property CanSeek As Boolean
+
    Get
+
      ' シークはサポートしない
+
      Return False
+
    End Get
+
  End Property
+

          
+
  Public Overrides ReadOnly Property CanRead As Boolean
+
    Get
+
      Return Not IsClosed
+
    End Get
+
  End Property
+

          
+
  Public Overrides ReadOnly Property CanWrite As Boolean
+
    Get
+
      ' 書き込みはサポートしない
+
      Return False
+
    End Get
+
  End Property
+

          
+
  Private ReadOnly Property IsClosed As Boolean
+
    Get
+
      Return reader Is Nothing
+
    End Get
+
  End Property
+

          
+
  Public Overrides Property Position As Long
+
    Get
+
      CheckDisposed()
+
      Throw New NotSupportedException()
+
    End Get
+
    Set(ByVal value As Long)
+
      CheckDisposed()
+
      Throw New NotSupportedException()
+
    End Set
+
  End Property
+

          
+
  Public Overrides ReadOnly Property Length As Long
+
    Get
+
      CheckDisposed()
+
      Throw New NotSupportedException()
+
    End Get
+
  End Property
+

          
+
  Public Property Volume As Integer
+
    Get
+
      CheckDisposed()
+
      Return _volume
+
    End Get
+
    Set(ByVal value As Integer)
+
      CheckDisposed()
+

          
+
      If value < 0 OrElse MaxVolume < value Then
+
        Throw New ArgumentOutOfRangeException("Volume", _
+
                                              value, _
+
                                              String.Format("0から{0}の範囲の値を指定してください", MaxVolume))
+
      End If
+

          
+
      _volume = value
+
    End Set
+
  End Property
+

          
+
  Public Sub New(ByVal baseStream As Stream)
+
    If baseStream Is Nothing Then Throw New ArgumentNullException("baseStream")
+
    If Not baseStream.CanRead Then Throw New ArgumentException("読み込み可能なストリームを指定してください", "baseStream")
+

          
+
    reader = New BinaryReader(baseStream)
+

          
+
    ReadHeader()
+
  End Sub
+

          
+
  Public Overrides Sub Close()
+
    If Not reader Is Nothing Then
+
      reader.Close()
+
      reader = Nothing
+
    End If
+
  End Sub
+

          
+
  ' dataチャンクまでのヘッダブロックの内容をバッファに読み込んでおく
+
  ' WAVEFORMAT等のヘッダ内容のチェックは省略
+
  Private Sub ReadHeader()
+
    Using headerStream As New MemoryStream()
+
      Dim writer As New BinaryWriter(headerStream)
+

          
+
      ' RIFFヘッダ
+
      Dim riffHeader() As Byte = reader.ReadBytes(12)
+

          
+
      writer.Write(riffHeader)
+

          
+
      ' dataチャンクまでの内容をwriterに書き写す
+
      Do
+
        Dim chunkHeader() As Byte = reader.ReadBytes(8)
+

          
+
        writer.Write(chunkHeader)
+

          
+
        Dim fourcc As Integer = BitConverter.ToInt32(chunkHeader, 0)
+
        Dim size As Integer = BitConverter.ToInt32(chunkHeader, 4)
+

          
+
        If fourcc = &h61746164 Then Exit Do 'data'
+

          
+
        writer.Write(reader.ReadBytes(size))
+
      Loop
+

          
+
      writer.Close()
+

          
+
      header = headerStream.ToArray()
+
    End Using
+
  End Sub
+

          
+
  Public Overrides Function Read(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer) As Integer
+
    CheckDisposed()
+

          
+
    If buffer Is Nothing Then Throw New ArgumentNullException("buffer")
+
    If offset < 0 Then Throw New ArgumentOutOfRangeException("offset", offset, "0以上の値を指定してください")
+
    IF count < 0 Then Throw New ArgumentOutOfRangeException("count", count, "0以上の値を指定してください")
+
    If buffer.Length - count < offset Then Throw New ArgumentException("配列の範囲を超えてアクセスしようとしました", "offset")
+

          
+
    If header Is Nothing Then
+
      ' dataチャンクの読み込み
+
      ' WAVEサンプルを読み込み、音量を適用して返す
+
      ' ストリームは16ビット(1サンプル2バイト)と仮定
+

          
+
      ' countバイト以下となるよう読み込むサンプル数を決定する
+
      Dim samplesToRead As Integer = count \ 2
+
      Dim bytesToRead As Integer = samplesToRead * 2
+
      Dim len As Integer = reader.Read(buffer, offset, bytesToRead)
+

          
+
      If len = 0 Then Return 0 ' 終端まで読み込んだ
+

          
+
      ' 読み込んだサンプル1つずつにボリュームを適用する
+
      For sample As Integer = 0 To samplesToRead - 1
+
        Dim s As Short = CShort(buffer(offset)) Or (CShort(buffer(offset + 1)) << 8)
+

          
+
        s = CShort((CInt(s) * _volume) \ MaxVolume)
+

          
+
        buffer(offset) = CByte(s And &hFF)
+
        buffer(offset + 1) = CByte((s >> 8) And &hFF)
+

          
+
        offset += 2
+
      Next
+

          
+
      Return len
+
    Else
+
      ' ヘッダブロックの読み込み
+
      ' バッファに読み込んでおいた内容をそのままコピーする
+
      Dim bytesToRead As Integer = Math.Min(header.Length - headerOffset, count)
+

          
+
      System.Buffer.BlockCopy(header, headerOffset, buffer, offset, bytesToRead)
+

          
+
      headerOffset += bytesToRead
+

          
+
      If headerOffset = header.Length Then
+
        ' ヘッダブロックを全て読み込んだ
+
        ' (不要になったヘッダのバッファを解放し、以降はdataチャンクの読み込みに移る)
+
        header = Nothing
+
      End If
+

          
+
      Return bytesToRead
+
    End If
+
  End Function
+

          
+
  Public Overrides Sub SetLength(ByVal value As Long)
+
    CheckDisposed()
+

          
+
    Throw New NotSupportedException()
+
  End Sub
+

          
+
  Public Overrides Function Seek(ByVal offset As Long, ByVal origin As SeekOrigin) As Long
+
    CheckDisposed()
+

          
+
    Throw New NotSupportedException()
+
  End Function
+

          
+
  Public Overrides Sub Flush()
+
    CheckDisposed()
+

          
+
    Throw New NotSupportedException()
+
  End Sub
+

          
+
  Public Overrides Sub Write(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer)
+
    CheckDisposed()
+

          
+
    Throw New NotSupportedException()
+
  End Sub
+

          
+
  Private Sub CheckDisposed()
+
    If IsClosed Then Throw New ObjectDisposedException(Me.GetType().FullName)
+
  End Sub
+

          
+
  Private reader As BinaryReader
+
  Private header() As Byte
+
  Private headerOffset As Integer = 0
+
  Private _volume As Integer = MaxVolume
+
  Private Const MaxVolume As Integer = 100
+
End Class
+
}}
+
#tabpage-end
+

          
+
*その他の変更方法
+
-[[Attenuating SoundPlayer Volume:http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/42b46e40-4d4a-48f8-8681-9b0167cfe781]] (&msdn(netfx,id,cc428831){waveOutSetVolume};を使った方法)
+

          
+

          

programming/netfx/tips/check_type_isassignablefrom_issubclassof/index.wiki.txt

current previous
211,7 211,7
 
Base.IsSubclassOf(Base) = False
Base.IsSubclassOf(Base) = False
 
}}
}}
 

        

        
~
継承関係ではなく実装しているインターフェイスなど、型が別の型に''代入可能かどうか''を判定したい場合は&msdn(netfx,member,System.Type.IsAssignableFrom){Type.IsAssignableFromメソッド};を使って調べることが出来る。
継承関係ではなく実装しているインターフェイスなど、型が別の型に''代入可能かどうか''を判定したい場合は&msdn(netfx,member,System.Type.IsAssignableFrom){IsAssignableFromメソッド};を使って調べることが出来る。
 

        

        
 
#tabpage(C#)
#tabpage(C#)
 
#code(cs){{
#code(cs){{
309,226 309,3
 
Class1.IsAssignableFrom(Class3) = True
Class1.IsAssignableFrom(Class3) = True
 
}}
}}
 

        

        
+
*基底クラスの取得
+
基底クラスが具体的にどのような型か実行時まで知り得ない場合は、&msdn(netfx,member,System.Type.BaseType){Type.BaseTypeプロパティ};を参照することで継承している型の情報を得ることができる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Base {}
+
class Class1 : Base {}
+
class Class2 : Class1 {}
+
class Class3 {}
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    Console.WriteLine("Class2.BaseType : {0}", typeof(Class2).BaseType);
+
    Console.WriteLine("Class3.BaseType : {0}", typeof(Class3).BaseType);
+
    Console.WriteLine();
+

          
+
    // Class2の継承ツリーを遡って表示する
+
    for (Type type = typeof(Class2); type != null; type = type.BaseType) {
+
      Console.WriteLine(type);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Base : End Class
+
Class Class1 : Inherits Base : End Class
+
Class Class2 : Inherits Class1 : End Class
+
Class Class3 : End Class
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine("Class2.BaseType : {0}", GetType(Class2).BaseType)
+
    Console.WriteLine("Class3.BaseType : {0}", GetType(Class3).BaseType)
+
    Console.WriteLine()
+

          
+
    ' Class2の継承ツリーを遡って表示する
+
    Dim type As Type = GetType(Class2)
+

          
+
    While Not type Is Nothing
+
      Console.WriteLine(type)
+

          
+
      type = type.BaseType
+
    End While
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Class2.BaseType : Class1
+
Class3.BaseType : System.Object
+

          
+
Class2
+
Class1
+
Base
+
System.Object
+
}}
+

          
+
*インターフェイスの取得
+
どのようなインターフェイスを実装しているか実行時まで知り得ない場合は、&msdn(netfx,member,System.Type.BaseType){Type.GetInterfacesメソッド};を使用することで型が実装しているインターフェイスすべてを得ることができる。 このメソッドでは、基底クラスで実装されているインターフェイスも返される。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
interface IIfc1 {}
+
interface IIfc2 {}
+
class Class1 : IIfc1 {}
+
class Class2 : IIfc1, IIfc2 {}
+
class Class3 : Class1, IIfc2 {}
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    Console.WriteLine("interfaces of Class1");
+
    foreach (Type ifc in typeof(Class1).GetInterfaces()) {
+
      Console.WriteLine(ifc);
+
    }
+
    Console.WriteLine();
+

          
+
    Console.WriteLine("interfaces of Class2");
+
    foreach (Type ifc in typeof(Class2).GetInterfaces()) {
+
      Console.WriteLine(ifc);
+
    }
+
    Console.WriteLine();
+

          
+
    Console.WriteLine("interfaces of Class3");
+
    foreach (Type ifc in typeof(Class3).GetInterfaces()) {
+
      Console.WriteLine(ifc);
+
    }
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Interface IIfc1 : End Interface
+
Interface IIfc2 : End Interface
+
Class Class1 : Implements IIfc1 : End Class
+
Class Class2 : Implements IIfc1, IIfc2 : End Class
+
Class Class3 : Inherits Class1 : Implements IIfc2 : End Class
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine("interfaces of Class1")
+
    For Each ifc As Type In GetType(Class1).GetInterfaces()
+
      Console.WriteLine(ifc)
+
    Next
+
    Console.WriteLine()
+

          
+
    Console.WriteLine("interfaces of Class2")
+
    For Each ifc As Type In GetType(Class2).GetInterfaces()
+
      Console.WriteLine(ifc)
+
    Next
+
    Console.WriteLine()
+

          
+
    Console.WriteLine("interfaces of Class3")
+
    For Each ifc As Type In GetType(Class3).GetInterfaces()
+
      Console.WriteLine(ifc)
+
    Next
+
    Console.WriteLine()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
interfaces of Class1
+
IIfc1
+

          
+
interfaces of Class2
+
IIfc1
+
IIfc2
+

          
+
interfaces of Class3
+
IIfc1
+
IIfc2
+

          
+
}}
+

          
+

          
+
*派生クラスの取得
+
基底クラスの型情報から、そのクラスから派生しているクラスの情報を直接得ることはできない。 そのため派生クラスを取得するには、&msdn(netfx,member,System.Reflection.Assembly.GetTypes){Assembly.GetTypesメソッド};を使ってアセンブリで定義されているすべての型情報を走査し、Type.BaseTypeプロパティを参照して基底クラスが一致するものを1つずつ検索する。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Reflection;
+

          
+
class Base {}
+
class Class1 : Base {}
+
class Class2 : Class1 {}
+
class Class3 {}
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    // Baseから派生している型を検索する
+
    Type targetType = typeof(Base);
+

          
+
    // 現在実行しているアセンブリで定義されているすべての型を列挙
+
    foreach (Type type in Assembly.GetExecutingAssembly().GetTypes()) {
+
      // 継承ツリーを遡って基底クラスを1つずつ調べる
+
      for (Type baseType = type.BaseType; baseType != null; baseType = baseType.BaseType) {
+
        if (baseType == targetType) {
+
          // 継承ツリーに目的の型と一致する型があった場合、表示する
+
          Console.WriteLine(type);
+
          break;
+
        }
+
      }
+
    }
+
  }
+
}
+

          
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Reflection
+

          
+
Class Base : End Class
+
Class Class1 : Inherits Base : End Class
+
Class Class2 : Inherits Class1 : End Class
+
Class Class3 : End Class
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    ' Baseから派生している型を検索する
+
    Dim targetType As Type = GetType(Base)
+

          
+
    ' 現在実行しているアセンブリで定義されているすべての型を列挙
+
    For Each type As Type In [Assembly].GetExecutingAssembly().GetTypes()
+
      ' 継承ツリーを遡って基底クラスを1つずつ調べる
+
      Dim baseType As Type = type.BaseType
+

          
+
      While Not baseType Is Nothing
+
        If baseType = targetType Then
+
          ' 継承ツリーに目的の型と一致する型があった場合、表示する
+
          Console.WriteLine(type)
+
          Exit While
+
        End If
+

          
+
        baseType = baseType.BaseType
+
      End While
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Class1
+
Class2
+

          
+
}}