[.net2] utiliser la compression de fichiers native de windows2000/xp

Description

Bien, cette source est à but pédagogique.
Ici je vous montre comment utiliser la compression interne de fichiers dans Windows2000/XP.
Le code est vraiment très simple, vous verrez à quel point cela est facile d'utiliser cette feature.

Liens MSDN:
http://windowssdk.msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/fsctl_set_compression.asp
http://windowssdk.msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/fsctl_get_compression.asp

Plusieurs exemples sont présent:
-Compression d'un fichier
-Décompression d'un fichier
-Compression d'un répertoire et sous-répetoires
-Indication si un fichier est compressé ou non
-Indication si le lecteur supporte la compression de fichiers.

Source / Exemple :


Imports System.Runtime.InteropServices
Imports System.Text
Imports System.io

''' <summary>
''' Classe appelant la compression/décompression IO interne de NT.
''' </summary>
''' <remarks></remarks>
Public Class NTInternalCompression

    ''' <summary>Methodes de compression pouvant etre utilisées.</summary>
    Enum COMPRESS_METHOD
        _DEFAULT = 1
        _LZNT1 = 2
    End Enum

    ''' <summary>Compresse un fichier.</summary>
    ''' <param name="path">Chemin du fichier.</param>
    ''' <param name="method">Méthode de compression.</param>
    ''' <returns>Retourne le numéro d'erreur.
    ''' 0 = Pas d'erreur, la compression a réussi.
    ''' -2 = Le volume dans lequel se trouve le fichier ne supporte pas la compression de fichiers.</returns>
    Shared Function CompressFile(ByVal path As String, Optional ByVal method As COMPRESS_METHOD = COMPRESS_METHOD._LZNT1) As Integer

        If CompressionIsSupported(path.Substring(0, 3)) Then

            Dim hPath As IntPtr = NativeMethods.CreateFile("\\.\" & path, NativeMethods.GENERIC_ALL, NativeMethods.FILE_SHARE_NONE, IntPtr.Zero, NativeMethods.OPEN_EXISTING, 0, IntPtr.Zero)

            Dim iBytesReturned As Integer = 0

            NativeMethods.SetIoCompression(hPath, NativeMethods.FSCTL_SET_COMPRESSION, method, Marshal.SizeOf(GetType(Short)), IntPtr.Zero, 0, iBytesReturned, IntPtr.Zero)

            NativeMethods.CloseHandle(hPath)

        Else
            Return -2
        End If

        Return Marshal.GetLastWin32Error

    End Function

    ''' <summary>Décompresse un fichier.</summary>
    ''' <param name="path">Chemin à décompresser.</param>
    ''' <returns>Retourne le numéro d'erreur. Si 0 pas d'erreur.
    ''' -1 = Le fichier n'est pas compressé donc pas de décompression possible.
    ''' -2 = Le volume dans lequel se trouve le fichier ne supporte pas la compression de fichiers.</returns>
    Shared Function UnCompressFile(ByVal path As String) As Integer

        If CompressionIsSupported(path.Substring(0, 3)) Then

            If FileCompressionState(path) Then

                Dim hPath As IntPtr = NativeMethods.CreateFile("\\.\" & path, NativeMethods.GENERIC_ALL, NativeMethods.FILE_SHARE_NONE, IntPtr.Zero, NativeMethods.OPEN_EXISTING, 0, IntPtr.Zero)

                Dim iBytesReturned As Integer = 0

                NativeMethods.SetIoCompression(hPath, NativeMethods.FSCTL_SET_COMPRESSION, NativeMethods.COMPRESSION_FORMAT_NONE, Marshal.SizeOf(GetType(Short)), IntPtr.Zero, 0, iBytesReturned, IntPtr.Zero)

                NativeMethods.CloseHandle(hPath)

            Else
                Return -1
            End If

        Else
            Return -2
        End If

        Return Marshal.GetLastWin32Error

    End Function

    ''' <summary>Indique si le fichier est compressé.</summary>
    ''' <param name="path">Chemin du fichier.</param>
    ''' <returns>True si compressé; False non compressé.</returns>
    Shared Function FileCompressionState(ByVal path As String) As Boolean

        If CompressionIsSupported(path.Substring(0, 3)) Then

            Dim hPath As IntPtr = NativeMethods.CreateFile("\\.\" & path, NativeMethods.GENERIC_ALL, NativeMethods.FILE_SHARE_NONE, IntPtr.Zero, NativeMethods.OPEN_EXISTING, 0, IntPtr.Zero)

            Dim iMethod As Short = -1
            Dim iBytesReturned As Integer = 0

            NativeMethods.GetIoCompression(hPath, NativeMethods.FSCTL_GET_COMPRESSION, 0, 0, iMethod, Marshal.SizeOf(GetType(Short)), iBytesReturned, IntPtr.Zero)

            NativeMethods.CloseHandle(hPath)

            If iMethod <> 0 Then Return True Else Return False

        Else
            Return False
        End If

    End Function

    ''' <summary>Indique si la compression de fichiers est supporté sur le lecteur.</summary>
    ''' <param name="volume">Lettre du lecteur.</param>
    ''' <returns>True si réussi; False si échoué.</returns>
    Shared Function CompressionIsSupported(ByVal volume As String) As Boolean

        Dim szVolBuff As New StringBuilder
        Dim szFSBuff As New StringBuilder
        Dim flags As Integer = 0

        UnsafeMethods.GetVolumeInformation(volume, szVolBuff, 128, Nothing, Nothing, flags, szFSBuff, 128)

        If flags And UnsafeMethods.FS_FILE_COMPRESSION Then Return True Else Return False

    End Function

    ''' <summary>Compresse un répertoire.</summary>
    ''' <param name="path">Chemin du répertoire.</param>
    ''' <param name="recursive">Inclut les sous-répertoires.</param>
    ''' <param name="method">Méthode de compression.</param>
    Shared Sub CompressDirectory(ByVal path As String, ByVal recursive As Boolean, Optional ByVal method As COMPRESS_METHOD = COMPRESS_METHOD._LZNT1)

        If CompressionIsSupported(path.Substring(0, 3)) Then

            Dim hPath As IntPtr = NativeMethods.CreateFile("\\.\" & path, NativeMethods.GENERIC_ALL, NativeMethods.FILE_SHARE_NONE, IntPtr.Zero, NativeMethods.OPEN_EXISTING, NativeMethods.FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero)

            Dim iBytesReturned As Integer = 0

            NativeMethods.SetIoCompression(hPath, NativeMethods.FSCTL_SET_COMPRESSION, method, Marshal.SizeOf(GetType(Short)), IntPtr.Zero, 0, iBytesReturned, IntPtr.Zero)

            NativeMethods.CloseHandle(hPath)

            'ajoute l'attribut de compression aux répertoires
            For Each curdir As String In Directory.GetDirectories(path, "*", Convert.ToInt32(recursive))

                hPath = NativeMethods.CreateFile("\\.\" & curdir, NativeMethods.GENERIC_ALL, NativeMethods.FILE_SHARE_NONE, IntPtr.Zero, NativeMethods.OPEN_EXISTING, NativeMethods.FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero)

                NativeMethods.SetIoCompression(hPath, NativeMethods.FSCTL_SET_COMPRESSION, method, Marshal.SizeOf(GetType(Short)), IntPtr.Zero, 0, iBytesReturned, IntPtr.Zero)

                NativeMethods.CloseHandle(hPath)

            Next

            'Compresse tout les fichiers trouvés dans les répertoires
            Dim files As String() = Directory.GetFiles(path, "*", Convert.ToInt32(recursive))
            If files.Length > 0 Then

                For i As Integer = 0 To files.Length - 1

                    hPath = NativeMethods.CreateFile("\\.\" & files(i), NativeMethods.GENERIC_ALL, NativeMethods.FILE_SHARE_NONE, IntPtr.Zero, NativeMethods.OPEN_EXISTING, 0, IntPtr.Zero)

                    NativeMethods.SetIoCompression(hPath, NativeMethods.FSCTL_SET_COMPRESSION, method, Marshal.SizeOf(GetType(Short)), IntPtr.Zero, 0, iBytesReturned, IntPtr.Zero)

                    NativeMethods.CloseHandle(hPath)

                Next

            End If

        Else

#If DEBUG Then
            Debug.WriteLine("Compression non supporté sur ce lecteur.")
#End If

        End If

    End Sub

End Class

Conclusion :


Testé uniquement sous XP Pro.

Bonne prog à tous :)

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.