NonSoft

フォルダをZIPファイル圧縮/解凍する
サンプル(VB.NET)


 サンプル(ソース/コード)
<このサンプルの概要>
J#.NET(vjslib.dll)を使用してフォルダをまるごと ZIPファイル圧縮/解凍するサンプルです。
フォルダを1つのファイルとしてバックアップする時に有効な方法だと思います。
色々調べましたがこれが一番良い方法では!??
参照設定にvjslibを追加してお試しください。このサンプルの動作環境として.NET Framework2.0と
J#.NET2.0で動作確認しています。VS.NET2005には.NET Framework2.0とJ#.NET2.0が含まれていますが、
.NET Framework2.0 ランタイムには J#.NET2.0ランタイムが含まれていませんので別途ダウンロード
する必要があります。

C#.NET版は フォルダをZIPファイル圧縮/解凍するサンプル(C#.NET) です。

このサンプルは空のフォルダもZIPに含めるようにしていますが、Compressed (zipped) Foldersで
見るとフォルダがファイルのように表示されたりします。しかし、解凍(というか展開)してみると
問題なく展開されます。空のフォルダも作成されます。疑問&調査中!!現在愛用しているフリーの
解凍ツールでは何の問題も無いのですが。

<このサンプルの見直しが必要な箇所>
(1)ファイルのクローズ処理はtry catch finallyで確実にクローズしましょう!!
(2)進捗状況が分かるようにした方が良いでしょう!!

★フォルダをZIPファイル圧縮/解凍するクラス(JZip.vb)
'****************************************************************************
' 機能名    : JZip.vb
' 機能説明  : ZIP圧縮/解凍クラス
' 備考      :
' 著作権    : Copyright(C) 2008 のん All rights reserved
' ---------------------------------------------------------------------------
' 使用条件  : このサイトの内容を使用(流用/改変/転載/等全て)した成果物を不特定
'           : 多数に公開/配布する場合は、このサイトを参考にした旨を記述してく
'           : ださい。(例)WEBページやReadMeにリンクを貼ってください
' ---------------------------------------------------------------------------
'****************************************************************************
''' <summary>
''' ZIP圧縮/解凍クラス
''' </summary>
''' <remarks></remarks>
Public Class JZip
    ''' <summary>
    ''' 圧縮
    ''' </summary>
    ''' <param name="zipFile">ZIPファイル</param>
    ''' <param name="srcPath">圧縮するFile/Folder</param>
    ''' <remarks></remarks>
    Public Shared Sub Compress(ByVal zipFile As String, ByVal srcPath As String)
        ' 圧縮するファイルの一覧作成
        Dim isFolder As Boolean = False
        Dim filePaths(0) As String
        If System.IO.Directory.Exists(srcPath) Then
            ' フォルダの時
            Dim fileLists As String = getFolderFileList(srcPath)
            If "".Equals(fileLists) = False Then
                filePaths = fileLists.Split(vbLf)
                isFolder = True
            End If
        Else
            ' ファイルの時
            filePaths(0) = srcPath
        End If

        ' ZIPファイルオープン
        Dim fos As java.io.FileOutputStream = New java.io.FileOutputStream(zipFile)
        Dim zos As java.util.zip.ZipOutputStream = New java.util.zip.ZipOutputStream(fos)

        ' ZIPにファイルを追加する
        For Each fpt As String In filePaths
            If "".Equals(fpt) Then Continue For

            ' ZIPに追加するときのファイル名を決定する
            Dim f As String
            If isFolder = False Then
                ' ディレクトリ無
                f = System.IO.Path.GetFileName(fpt)
            Else
                ' ディレクトリ有
                f = fpt.Remove(0, srcPath.Length)
            End If
            If "\".Equals(f.Substring(0, 1)) Then f = f.Substring(1)
            f = f.Replace("\", "/")

            ' エントリ作成
            Dim ze As java.util.zip.ZipEntry = New java.util.zip.ZipEntry(f)

            ' 圧縮メソッドを設定
            ze.setMethod(java.util.zip.ZipEntry.DEFLATED)

            ' 更新日時設定
            ze.setTime(toEpochTime(System.IO.File.GetLastWriteTime(fpt)))

            ' エントリ追加
            zos.putNextEntry(ze)

            ' 圧縮データ書込
            If "\".Equals(fpt.Substring(fpt.Length - 1)) = False Then
                Dim len As Integer
                Dim buffer(8192 - 1) As SByte
                ' ファイルオープン
                Dim fis As java.io.FileInputStream = New java.io.FileInputStream(fpt)
                ' ファイル読込み
                Do While True
                    len = fis.read(buffer, 0, buffer.Length)
                    If len <= 0 Then
                        Exit Do
                    End If
                    ' ファイル書込み
                    zos.write(buffer, 0, len)
                Loop
                ' 閉じる
                fis.close()
            End If

            ' 閉じる
            zos.closeEntry()
            Application.DoEvents()
        Next

        ' ZIPファイルクローズ
        zos.close()
        fos.close()
    End Sub

    ''' <summary>
    ''' 解凍
    ''' </summary>
    ''' <param name="zipFile">ZIPファイル</param>
    ''' <param name="dstPath">解凍するFolder</param>
    ''' <remarks></remarks>
    Public Shared Sub Extract(ByVal zipFile As String, ByVal dstPath As String)
        ' フォルダ作成
        If System.IO.Directory.Exists(dstPath) = False Then
            System.IO.Directory.CreateDirectory(dstPath)
        End If

        ' ZIPファイルオープン
        Dim fis As java.io.FileInputStream = New java.io.FileInputStream(zipFile)
        Dim zis As java.util.zip.ZipInputStream = New java.util.zip.ZipInputStream(fis)

        ' ZIP内のファイル情報を取得
        Do While True
            Dim ze As java.util.zip.ZipEntry = zis.getNextEntry()
            If ze Is Nothing Then Exit Do

            ' ファイル名取得
            Dim fileName As String = ze.getName()

            ' 解凍先のパス設定
            Dim fullPath As String = System.IO.Path.Combine(dstPath, fileName)
            fullPath = fullPath.Replace("/", "\")

            If ze.isDirectory() = False Then
                Dim len As Integer
                Dim buffer(8192 - 1) As SByte

                ' ファイルオープン
                Dim fos As java.io.FileOutputStream = New java.io.FileOutputStream(fullPath)

                ' ファイル読込み
                Do While True
                    len = zis.read(buffer, 0, buffer.Length)
                    If len <= 0 Then
                        Exit Do
                    End If
                    fos.write(buffer, 0, len)
                Loop

                ' 閉じる
                fos.close()
                ' ファイルの更新日時設定
                System.IO.File.SetLastWriteTime(fullPath, fromEpochTime(ze.getTime()))
            Else
                ' フォルダ作成
                System.IO.Directory.CreateDirectory(fullPath)
            End If
            Application.DoEvents()
        Loop

        ' ZIPファイルクローズ
        zis.close()
        fis.close()
    End Sub

    ''' <summary>
    ''' フォルダとファイルの一覧を取得
    ''' </summary>
    ''' <param name="srcPath">一覧取得するFolder</param>
    ''' <returns>フォルダとファイルの一覧(改行区切り)</returns>
    ''' <remarks></remarks>
    Private Shared Function getFolderFileList(ByVal srcPath As String) As String
        Dim flist As String = ""
        Dim current As System.IO.DirectoryInfo = New System.IO.DirectoryInfo(srcPath)

        ' ファイルの一覧作成
        For Each fpt As System.IO.FileInfo In current.GetFiles
            If "".Equals(flist) = False Then flist &= vbLf
            flist &= fpt.FullName
        Next

        ' フォルダの一覧作成
        For Each dir As System.IO.DirectoryInfo In current.GetDirectories
            If "".Equals(flist) = False Then flist &= vbLf
            flist += dir.FullName + "\"
            Dim str As String = getFolderFileList(dir.FullName)
            If "".Equals(str) = False Then
                If "".Equals(flist) = False Then flist &= vbLf
                flist &= str
            End If
        Next

        Application.DoEvents()
        Return flist
    End Function

    ''' <summary>
    ''' DateTimeをエポック値に変換する
    ''' </summary>
    ''' <param name="dt"></param>
    ''' <returns>DateTime</returns>
    ''' <remarks>エポック値</remarks>
    Private Shared Function toEpochTime(ByVal dt As DateTime) As Long
        Dim epo As Long = (dt.ToUniversalTime().Ticks - 621355968000000000) / 10000
        Return epo
    End Function

    ''' <summary>
    ''' エポック値をDateTimeに変換する
    ''' </summary>
    ''' <param name="epo"></param>
    ''' <returns>エポック値</returns>
    ''' <remarks>DateTime</remarks>
    Private Shared Function fromEpochTime(ByVal epo As Long) As DateTime
        Dim dt As DateTime = New DateTime(epo * 10000 + 621355968000000000)
        Return dt.ToLocalTime()
    End Function
End Class

★テスト用フォーム(Form1.vb)
Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles Button1.Click
        ' フォルダ圧縮
        JZip.Compress("d:\temp\test.zip", "d:\temp\test1")
        ' 解凍
        JZip.Extract("d:\temp\test.zip", "d:\temp\test2")
        ' ファイル圧縮
        JZip.Compress("d:\temp\test.zip", "d:\temp\test3\test3.txt")
        ' 解凍
        JZip.Extract("d:\temp\test.zip", "d:\temp\test4")
    End Sub
End Class