GZipStream to compress/extract 2 files

StewartBW 1,145 Reputation points
2024-04-12T00:40:36.7033333+00:00

Hello

Here's an excellent sample to zip and unzip a single file using GZip:

https://learn.microsoft.com/en-us/dotnet/api/system.io.compression.gzipstream?view=netframework-4.0

Any idea how to include 2 files to compress and how to extract them back? Possible?

Thanks.

  • .Net 4.0 full profile, so no Zip class, can't use 3rd party dlls, so need to stay with GZipStream :(
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,922 questions
VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,727 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jiachen Li-MSFT 31,321 Reputation points Microsoft Vendor
    2024-04-12T06:37:01.1866667+00:00

    Hi @StewartBW ,

    You can first create a temporary directory, then compress each file individually into that directory, and finally compress the directory itself into a single .gz file.

    And to ensure that the extracted files retain their original names and content, you need to store that information during compression and restore it during extraction.

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            Dim file1 As String = "C:\Users\Administrator\Desktop\file1.txt"
            Dim file2 As String = "C:\Users\Administrator\Desktop\file2.txt"
            Dim compressedFile As String = "C:\Users\Administrator\Desktop\compressed_files.gz"
    
            CompressFilesIntoGZip({file1, file2}, compressedFile)
    
        End Sub
    
        Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
            Dim compressedFile As String = "C:\Users\Administrator\Desktop\compressed_files.gz"
    
            Dim outputDirectory As String = "C:\Users\Administrator\Desktop\extracted_files"
    
            ExtractFilesFromGZip(compressedFile, outputDirectory)
        End Sub
    
        Private Sub CompressFilesIntoGZip(files As String(), compressedFile As String)
            Using outputStream As FileStream = File.Create(compressedFile)
                Using gzipStream As New GZipStream(outputStream, CompressionMode.Compress)
                    For Each f In files
                        Dim fileInfo As New FileInfo(f)
                        Dim fileSizeBytes As Long = fileInfo.Length
    
                        ' Write file name and size to the compressed stream
                        Dim fileNameBytes() As Byte = Encoding.UTF8.GetBytes(fileInfo.Name)
                        gzipStream.Write(BitConverter.GetBytes(fileNameBytes.Length), 0, 4)
                        gzipStream.Write(fileNameBytes, 0, fileNameBytes.Length)
                        gzipStream.Write(BitConverter.GetBytes(fileSizeBytes), 0, 8)
    
                        ' Write file content to the compressed stream
                        Using inputFileStream As FileStream = File.OpenRead(f)
                            inputFileStream.CopyTo(gzipStream)
                        End Using
                    Next
                End Using
            End Using
    
            Console.WriteLine($"Files {String.Join(", ", files)} compressed into {compressedFile}")
        End Sub
    
        Private Sub ExtractFilesFromGZip(compressedFile As String, outputDirectory As String)
            ' Create a directory to extract files into
            Directory.CreateDirectory(outputDirectory)
    
            Using inputStream As FileStream = File.OpenRead(compressedFile)
                Using gzipStream As New GZipStream(inputStream, CompressionMode.Decompress)
                    While True
                        ' Read file name length
                        Dim fileNameLengthBuffer(3) As Byte
                        Dim bytesRead As Integer = gzipStream.Read(fileNameLengthBuffer, 0, 4)
                        If bytesRead = 0 Then Exit While
    
                        ' Read file name
                        Dim fileNameLength As Integer = BitConverter.ToInt32(fileNameLengthBuffer, 0)
                        Dim fileNameBytes(fileNameLength - 1) As Byte
                        gzipStream.Read(fileNameBytes, 0, fileNameLength)
                        Dim fileName As String = Encoding.UTF8.GetString(fileNameBytes)
    
                        ' Read file size
                        Dim fileSizeBuffer(7) As Byte
                        gzipStream.Read(fileSizeBuffer, 0, 8)
                        Dim fileSize As Long = BitConverter.ToInt64(fileSizeBuffer, 0)
    
                        ' Create the output file path
                        Dim extractedFilePath As String = Path.Combine(outputDirectory, fileName)
    
                        ' Write file content to the output file
                        Using outputFileStream As New FileStream(extractedFilePath, FileMode.Create, FileAccess.Write)
                            Dim buffer(4096) As Byte
                            Dim totalBytesRead As Integer = 0
                            While totalBytesRead < fileSize
                                Dim bytesToRead As Integer = Math.Min(buffer.Length, CInt(fileSize - totalBytesRead))
                                Dim bytesReadThisTime As Integer = gzipStream.Read(buffer, 0, bytesToRead)
                                If bytesReadThisTime = 0 Then Exit While
                                outputFileStream.Write(buffer, 0, bytesReadThisTime)
                                totalBytesRead += bytesReadThisTime
                            End While
                        End Using
                    End While
                End Using
            End Using
    
            Console.WriteLine($"Files extracted from {compressedFile} to {outputDirectory}")
        End Sub
    
    

    Best Regards.

    Jiachen Li


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.