このチュートリアルでは、次のような zip ファイルの操作方法について説明します。
最終アプリケーションは、次の図のように表示されます。
新しい Visual Studio プロジェクトを開始します。
Button | Button.Text Property | Button.Name Property |
---|---|---|
1 | Create Zip File… | btnNew |
2 | Open Zip File… | btnOpen |
3 | Add Files… | btnAdd |
4 | Extract Files | btnExtract |
5 | Remove Files | btnRemove |
6 | View File | btnView |
7 | Test Zip File | btnTest |
メモ: [ColumnHeader コレクションエディタ]には、[ListView タスク]メニューの[列の編集]をクリックしてアクセスすることもできます。[ListView タスク]メニューにアクセスするには、ListView コントロールの右上隅にあるスマートタグ をクリックします。
[ColumnHeader コレクションエディタ]は次のようになります。
列ヘッダを表示するには、[プロパティ]ウィンドウで[表示]プロパティを[詳細]に設定するか、[ListView タスク]メニューの[表示]ドロップダウンボックスから[詳細]を選択します。
ソリューションエクスプローラウィンドウに移動し、[参照]を右クリックし、[参照の追加]メニューオプションを選択します。リストから C1.C1Zip アセンブリを選択するか、ファイルを参照して C1.C1Zip.2.dll ファイルを探します。
[Form1.vb]タブ(C# では[Form1.cs]タブ)を選択するか、[表示]→[コード]を選択して、コードエディタを開きます。ファイルの上部に、次のディレクティブを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Imports System.IO Imports C1.C1Zip |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
using System.IO; using C1.C1Zip; |
これで、C1Zip アセンブリと System.IO アセンブリで定義されているオブジェクトがプロジェクトに表示されます。
コードエディタに切り替えて、次のデータメンバ宣言を入力するかコピーします。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private m_Zip As C1ZipFile |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private m_Zip As C1ZipFile; |
これは、このアプリケーションのメインオブジェクトです。このオブジェクトは、zip ファイルの処理に使用されるメソッドを実装しています。
Form_Load イベントに次のコードを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' C1ZipFile メンバを作成します。 m_Zip = New C1ZipFile() End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void Form1_Load(object sender, EventArgs e) { // C1ZipFile メンバを作成します。 m_Zip = new C1ZipFile(); } |
このコードは、新しい C1ZipFile オブジェクトを作成し、それを m_Zip メンバに代入します。この C1ZipFile オブジェクトはまだ使用できないことに注意してください。それには、最初に Open メソッドを使用して既存の zip ファイルにアタッチするか、Create メソッドを使用して新しい zip ファイルにアタッチする必要があります。
[Zip ファイルの作成]コマンドボタンの Click イベントを処理する次のコードを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click ' ファイルを開くダイアログを表示します。 Dim fo As SaveFileDialog = New SaveFileDialog() fo.FileName = "*.zip" If fo.ShowDialog() <> Windows.Forms.DialogResult.OK Then Exit Sub End If ' zip ファイルを開きます。 Try m_Zip.Create(fo.FileName) Catch MessageBox.Show("Can't create ZIP file, please try again.", "C1Zip") End Try ' UI を更新します。 UpdateDisplay() End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void btnNew_Click(object sender, EventArgs e) { // ファイルを開くダイアログを表示します。 SaveFileDialog fo = new SaveFileDialog(); fo.FileName = "*.zip"; if (fo.ShowDialog() != DialogResult.OK ) return; // zip ファイルを開きます。 try { m_Zip.Create(fo.FileName); } catch { MessageBox.Show("Can't create ZIP file, please try again.", "C1Zip"); } // UI を更新します。 UpdateDisplay(); } |
[Zip ファイルを開く]コマンドボタンの Click イベントを処理する次のコードを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub btnOpen_Click(sender As Object, e As EventArgs) Handles btnOpen.Click ' ファイルを開くダイアログを表示します。 Dim fo As OpenFileDialog = New OpenFileDialog() fo.FileName = "*.zip" If fo.ShowDialog() <> Windows.Forms.DialogResult.OK Then Exit Sub Try m_Zip.Open(fo.FileName) Catch MessageBox.Show("Invalid ZIP file, please try again.") End Try ' UI を更新します。 UpdateDisplay() End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void btnOpen_Click(object sender, EventArgs e) { // ファイルを開くダイアログを表示します。 OpenFileDialog fo = new OpenFileDialog(); fo.FileName = "*.zip"; if (fo.ShowDialog() != DialogResult.OK ) return; try { m_Zip.Open(fo.FileName); } catch { MessageBox.Show("Invalid ZIP file, please try again."); } // UI を更新します。 UpdateDisplay(); } |
重要な行は、C1ZipFile オブジェクトの Open メソッドの呼び出しです。ここで、オブジェクトを既存の zip ファイルにアタッチします。Try/Catch ステートメントは、主に、ユーザーが zip ファイルでないファイルを選択した場合に対処するために使用されます。
ファイルが開いたら、UpdateDisplay ユーティリティ関数を呼び出して、zip ファイルの内容を表示します。
次に、zip ファイルの内容を表示する UpdateDisplay ユーティリティ関数を追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub UpdateDisplay() ' ListView コントロールを更新して、zip ファイルの内容を表示します。 With ListView1 ' 既存の項目を削除します。 .Items.Clear() ' 各エントリを追加します。 Dim ze As C1ZipEntry For Each ze In m_Zip.Entries ' 圧縮量を計算します。 Dim pct As Double = 0 If ze.SizeUncompressed > 0 Then pct = 1 - ze.SizeCompressed / ze.SizeUncompressed End If ' ListView 項目を構築します。 Dim items(4) As String items(0) = ze.FileName items(1) = Format(ze.Date, "MM/dd/yy") items(2) = Format(ze.SizeUncompressed, "#,##0") items(3) = Format(ze.SizeCompressed, "#,##0") items(4) = Format(pct, "00 %") Dim lvi As ListViewItem = New ListViewItem(items) ' ZipEntry を項目タグに保存します。 lvi.Tag = ze ' 項目を ListView に追加します。 .Items.Add(lvi) Next ze ' UI を更新します。 Dim hasEntries As Boolean = (.Items.Count > 0) btnExtract.Enabled = hasEntries btnRemove.Enabled = hasEntries btnTest.Enabled = hasEntries End With End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void UpdateDisplay() { // 既存の項目を削除します。 listView1.Items.Clear(); // 各エントリを追加します。 foreach (C1ZipEntry ze in m_Zip.Entries) { // 圧縮量を計算します。 double pct = 0; if (ze.SizeUncompressed > 0) { pct = 1 - (((double)ze.SizeCompressed) / ((double)ze.SizeUncompressed)); } // ListView 項目を構築します。 ListViewItem lvi = new ListViewItem(new string[] { ze.FileName, Microsoft.VisualBasic.Strings.Format(ze.Date, "MM/dd/yy"), Microsoft.VisualBasic.Strings.Format(ze.SizeUncompressed, "#,##0"), Microsoft.VisualBasic.Strings.Format(ze.SizeCompressed, "#,##0"), Microsoft.VisualBasic.Strings.Format(pct, "00 %") }); // ZipEntry を項目タグに保存します。 lvi.Tag = ze; // 項目を ListView に追加します。 listView1.Items.Add(lvi); } // UI を更新します。 bool hasEntries = (listView1.Items.Count > 0); btnExtract.Enabled = hasEntries; btnRemove.Enabled = hasEntries; btnTest.Enabled = hasEntries; } |
重要な行は、最初の C1ZipEntry オブジェクトの宣言と、そのオブジェクトを ForEach ループ内で使用して zip ファイル内のエントリ(m_Zip.Entries)を処理するコードです。
各エントリに対して、C1ZipEntry オブジェクトから抽出された情報を格納する ListViewItem を作成し、新しいエントリを ListView コントロールに追加します。C1ZipEntry オブジェクト自体は ListView 項目の Tag プロパティに保存されます。
最後に、抽出、削除、またはテスト可能なエントリがあるかどうかに応じて、コマンドボタンを有効/無効にします。
[Zip ファイルのテスト]コマンドボタンの Click イベントを処理する次のコードを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click ' 各エントリをテストします。 Dim ze As C1ZipEntry For Each ze In m_Zip.Entries If Not ze.CheckCRC32() Then MessageBox.Show("** Entry " & ze.FileName & " has errors.", "C1Zip", MessageBoxButtons.OK, MessageBoxIcon.Error) Exit Sub End If Next ' ここまで到達すれば問題はありません。 MessageBox.Show("All entries passed CRC check", "C1Zip") End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void btnTest_Click(object sender, EventArgs e) { // 各エントリをテストします。 foreach (C1ZipEntry ze in m_Zip.Entries) { if (!ze.CheckCRC32()) { MessageBox.Show("** Entry " + ze.FileName + " has errors.", "C1Zip", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } // ここまで到達すれば問題はありません。 MessageBox.Show("All entries passed CRC check", "C1Zip"); } |
重要な行は、C1ZipEntry 変数の宣言と、その変数を使用して zip ファイル内のエントリをループするコードです。次に、各エントリに対して CheckCRC32 メソッドを呼び出して、ファイルに保存されているバイトデータの実際のチェックサムがエントリヘッダに保存されているチェックサムと一致するかどうかを確認します。この関数は、値が一致する場合は true を返します。値が一致しない場合は、false を返して、エントリが破損していることを示します。
[ファイルの表示]コマンドボタンの Click イベントを処理する次のコードを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub btnView_Click(sender As Object, e As EventArgs) Handles btnView.Click ' 最初に選択されたディレクトリではない項目を取得します。 Dim ze As C1ZipEntry = Nothing Dim lvi As ListViewItem For Each lvi In ListView1.SelectedItems Dim zeItem As C1ZipEntry = lvi.Tag If (zeItem.Attributes And FileAttributes.Directory) = 0 Then ze = zeItem Exit For End If Next lvi ' 項目を取得したことを確認します。 If ze Is Nothing Then MessageBox.Show("Sorry, no files to show...", "C1Zip") Exit Sub End If ' エントリの内容を文字列に読み取ります。 Dim entry As Stream = ze.OpenReader() Dim sr As StreamReader = New StreamReader(entry) Dim entryText As String = sr.ReadToEnd() entry.Close() ' エントリが MessageBox に対して長すぎないようにします。 If entryText.Length > 16000 Then entryText = entryText.Substring(0, 16000) End If ' メッセージボックスにエントリを表示します。 MessageBox.Show(entryText, ze.FileName) End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void btnView_Click(object sender, EventArgs e) { // 最初に選択されたディレクトリではない項目を取得します。 C1ZipEntry ze = null; foreach (ListViewItem lvi in listView1.SelectedItems) { C1ZipEntry zeItem = lvi.Tag as C1ZipEntry; if ((zeItem.Attributes == 0) && (FileAttributes.Directory == 0)) { ze = zeItem; break; } } // 項目を取得したことを確認します。 if (ze == null ) { MessageBox.Show("Sorry, no files to show...", "C1Zip"); return; } // エントリの内容を文字列に読み取ります。 Stream entry = ze.OpenReader(); StreamReader sr = new StreamReader(entry); string entryText = sr.ReadToEnd(); entry.Close(); // エントリが MessageBox に対して長すぎないようにします。 if (entryText.Length > 16000 ) { entryText = entryText.Substring(0, 16000); } // メッセージボックスにエントリを表示します。 MessageBox.Show(entryText, ze.FileName); } |
この関数は、最初に選択されたサブディレクトリではない zip エントリを選択します。有効なエントリが見つからない場合、関数は終了します。
次に、 OpenReader メソッドを呼び出して、エントリの内容の読み取りに使用できるストリームを取得します。この手順には、一時ファイルも余分な遅延もありません。データは、ストリームから読み取られると同時に展開されます。
次に、StreamReader オブジェクトの ReadToEnd メソッドを使用して、エントリの内容を文字列に直接読み取った後、ストリームを閉じます。
最後に、文字列を切り詰めてメッセージボックスに表示します。
この関数は、短いテキストファイルの内容を表示することを目的としています。バイナリファイルの内容を表示しようとすると、数文字しか表示されません。
[ファイルの追加]コマンドボタンの Click イベントを処理する次のコードを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click ' 追加するファイルのリストを取得します。 Dim fo As OpenFileDialog = New OpenFileDialog() fo.Multiselect = True fo.FileName = "*.*" If fo.ShowDialog <> Windows.Forms.DialogResult.OK Then Exit Sub ' リストにファイルを追加します。 Dim file As String For Each file In fo.FileNames() m_Zip.Entries.Add(file) Next file ' 完了。 UpdateDisplay() End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void btnAdd_Click(object sender, EventArgs e) { // 追加するファイルのリストを取得します。 OpenFileDialog fo = new OpenFileDialog(); fo.Multiselect = true; fo.FileName = "*.*"; if (fo.ShowDialog() == DialogResult.OK) { // リストにファイルを追加します。 foreach (string file in fo.FileNames) { m_Zip.Entries.Add(file); } // 完了。 UpdateDisplay(); } } |
zip ファイルに新しいエントリを追加することは簡単です。重要な行は、C1ZipFile オブジェクトの Add メソッドの呼び出しだけです。ここで、追加するファイルの完全名を文字列で渡します。これで、やることはすべてです。
[ファイルの抽出]コマンドボタンの Click イベントを処理する次のコードを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub btnExtract_Click(sender As Object, e As EventArgs) Handles btnExtract.Click ' いくつかのエントリを選択していることを確認します。 Dim cnt As Integer = ListView1.SelectedIndices.Count If cnt = 0 Then MessageBox.Show("Sorry, no files to extract...", "C1Zip") Exit Sub End If ' ユーザーに確認します。 Dim dr As DialogResult Dim msg As String msg = "Please confirm that you want to extract " + cnt.ToString() + " entries." dr = MessageBox.Show(msg, "C1Zip", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) If dr <> Windows.Forms.DialogResult.OK Then Exit Sub ' 選択されたすべてのエントリを抽出します。 Dim lvi As ListViewItem Dim ze As C1ZipEntry For Each lvi In ListView1.SelectedItems ze = lvi.Tag If ze.SizeCompressed > 0 Then m_Zip.Entries.Extract(ze.FileName) End If Next lvi ' 完了。 UpdateDisplay() End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void btnExtract_Click(object sender, EventArgs e) { // いくつかのエントリを選択していることを確認します。 int cnt = listView1.SelectedIndices.Count; if (cnt == 0) { MessageBox.Show("Sorry, no files to extract...", "C1Zip"); return; } // ユーザーに確認します。 DialogResult dr; string msg; msg = "Please confirm that you want to extract " + cnt.ToString() + " entries."; dr = MessageBox.Show(msg, "C1Zip", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if ( dr != DialogResult.OK ) return; // 選択されたすべてのエントリを抽出します。 C1ZipEntry ze; foreach (ListViewItem lvi in ListView1.SelectedItems) { ze = (C1ZipEntry)lvi.Tag; if ( ze.SizeCompressed > 0 ) { m_Zip.Entries.Extract(ze.FileName); } } // 完了。 UpdateDisplay(); } |
最も重要な行は、C1ZipFile オブジェクトの Entries プロパティの Extract メソッドの呼び出しです。 パラメータは、エントリのファイル名を含む文字列です。これは、エントリの FileName プロパティに保存されています。).
デフォルトでは、Extract メソッドはエントリを展開し、それを zip ファイルのディレクトリに保存します。このメソッドには別のバージョンもあります。そこでは、出力ディレクトリと展開ファイルのファイル名を指定できます。詳細については、「C1.C1Zip 名前空間 」セクションを参照してください。
[ファイルの削除]コマンドボタンの Click イベントを処理する次のコードを追加します。
Visual Basic でコードを書く場合
Visual Basic |
コードのコピー
|
---|---|
Private Sub btnRemove_Click(sender As Object, e As EventArgs) Handles btnRemove.Click ' いくつかのエントリを選択していることを確認します。 Dim cnt As Integer = ListView1.SelectedIndices.Count If cnt = 0 Then MessageBox.Show("Oops, no files to remove...", "C1Zip") Exit Sub End If ' ユーザーに確認します。 Dim dr As DialogResult Dim msg As String msg = "Please confirm that you want to delete " + cnt.ToString() + " entries." dr = MessageBox.Show(msg, "C1Zip", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) If dr <> Windows.Forms.DialogResult.OK Then Exit Sub ' 選択されたすべてのエントリを削除します。 Dim lvi As ListViewItem Dim ze As C1ZipEntry For Each lvi In ListView1.SelectedItems ze = lvi.Tag m_Zip.Entries.Remove(ze.FileName) Next lvi ' 完了。 UpdateDisplay() End Sub |
C# でコードを書く場合
C# |
コードのコピー
|
---|---|
private void btnRemove_Click(object sender, EventArgs e) { // いくつかのエントリを選択していることを確認します。 int cnt = listView1.SelectedIndices.Count; if (cnt == 0 ) { MessageBox.Show("Oops, no files to remove...", "C1Zip"); return; } // ユーザーに確認します。 DialogResult dr; string msg; msg = "Please confirm that you want to delete " + cnt.ToString() + " entries."; dr = MessageBox.Show(msg, "C1Zip", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if (dr != DialogResult.OK) return; // 選択されたすべてのエントリを削除します。 foreach (ListViewItem lvi in listView1.SelectedItems) { C1ZipEntry ze = (C1ZipEntry)lvi.Tag; if (ze.SizeCompressed > 0) { m_Zip.Entries.Remove(ze.FileName); } } // 完了。 UpdateDisplay(); } |
最も重要な行は、C1ZipFile オブジェクトの Entries プロパティの Remove メソッドの呼び出しです。パラメータは、エントリのファイル名を含む文字列です。これは、エントリの FileName プロパティに保存されています。
これで「Zip ファイルの処理」チュートリアルは終了です。