Click here to Skip to main content
15,890,186 members
Articles / Programming Languages / C#

GZipStream - Compress/Decompress a String

Rate me:
Please Sign up or sign in to vote.
2.64/5 (16 votes)
23 Jun 2008CPOL1 min read 269.1K   41   32
An article on how use GZipStream with string as input parameter.

Introduction

This article presents two methods to compress and decompress strings using System.IO.Compression.GZipStream.

Context/Problem

After converting code from VB.NET 1.1 to C#.NET 3.5, I needed to change some code using a third party zip class to GZipStream. Code samples found on the web or on VS help were presenting solutions dealing with FileStream but in this case, a string is given as an input parameter.

So the little challenge was to go from a string to a byte array (byte[]) and vice versa without losing a char nor changing its encoding because I ended up finding that System.Text.Encoding.Unicode.GetBytes()/GetString() previously used in the VB code was not acting properly, resulting in a loss of characters. Plus the Flush() method on GZipStream with the compression option doesn't flush everything...

Tips

So as I found no method transforming a string into a byte[] and vice versa without involving encoding specifications, I ended up with a loop and a cast. If you have a better idea, please tell me so.

And I found out, if you only flush a GZipStream instance and retrieve the data from the underlying stream without closing this GZipStream instance, you miss part of the data.

The Code

Compress/zip a string:

C#
public static string Zip(string value)
{
    //Transform string into byte[]
    byte[] byteArray = new byte[value.Length];
    int indexBA = 0;
    foreach (char item in value.ToCharArray())
    {
        byteArray[indexBA++] = (byte)item;
    }

    //Prepare for compress
    System.IO.MemoryStream ms = new System.IO.MemoryStream();
    System.IO.Compression.GZipStream sw = new System.IO.Compression.GZipStream(ms,
        System.IO.Compression.CompressionMode.Compress);

    //Compress
    sw.Write(byteArray, 0, byteArray.Length);
    //Close, DO NOT FLUSH cause bytes will go missing...
    sw.Close();

    //Transform byte[] zip data to string
    byteArray = ms.ToArray();
    System.Text.StringBuilder sB = new System.Text.StringBuilder(byteArray.Length);
    foreach (byte item in byteArray)
    {
        sB.Append((char)item);
    }
    ms.Close();
    sw.Dispose();
    ms.Dispose();
    return sB.ToString();
}

Decompress/Unzip a string: input value has been previously compressed with GZipStream.

C#
public static string UnZip(string value)
{
    //Transform string into byte[]
    byte[] byteArray = new byte[value.Length];
    int indexBA = 0;
    foreach (char item in value.ToCharArray())
    {
        byteArray[indexBA++] = (byte)item;
    }

    //Prepare for decompress
    System.IO.MemoryStream ms = new System.IO.MemoryStream(byteArray);
    System.IO.Compression.GZipStream sr = new System.IO.Compression.GZipStream(ms,
        System.IO.Compression.CompressionMode.Decompress);

    //Reset variable to collect uncompressed result
    byteArray = new byte[byteArray.Length];

    //Decompress
    int rByte = sr.Read(byteArray, 0, byteArray.Length);

    //Transform byte[] unzip data to string
    System.Text.StringBuilder sB = new System.Text.StringBuilder(rByte);
    //Read the number of bytes GZipStream red and do not a for each bytes in
    //resultByteArray;
    for (int i = 0; i < rByte; i++)
    {
        sB.Append((char)byteArray[i]);
    }
    sr.Close();
    ms.Close();
    sr.Dispose();
    ms.Dispose();
    return sB.ToString();
}

Points of Interest

Well, if you haven't dealt with a lot of streams like me, hopefully this will avoid loss of time!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Suggestiontransforming a string into a byte[] and vice versa without involving encoding specifications Pin
Member 1383323917-May-18 22:39
Member 1383323917-May-18 22:39 
QuestionLosing Data Pin
Mansoor ali P11-Apr-16 18:35
Mansoor ali P11-Apr-16 18:35 
QuestionUse this code instead Pin
Jason Jakob17-Dec-14 12:28
Jason Jakob17-Dec-14 12:28 
SuggestionThanks & a small correction! Pin
amitthk29-Sep-14 7:28
professionalamitthk29-Sep-14 7:28 
GeneralMy vote of 1 Pin
Yclkvnc8-May-13 6:28
Yclkvnc8-May-13 6:28 
GeneralMy vote of 4 Pin
Nasenbaaer12-Apr-13 6:24
Nasenbaaer12-Apr-13 6:24 
SuggestionSharing my code Pin
SamNaseri16-Nov-11 18:38
SamNaseri16-Nov-11 18:38 
For a couple of reason I decided to post another piece of code that may be useful for you.

1. This code has some problems that already mentioned in other messages below.
2. My variation is based on Encoding. People who search the web and came to this page may not be concerned about Encoding dropping some letters, or they may even do not believe such a problem exists. So this variation is for those who want to use Encoding for converting text to byte[] and vice versa.

Here is the code:

C#
public class Zip
{
    //public static Encoding Encoding = System.Text.Encoding.Unicode;
    public static byte[] Compress(string text, Encoding Encoding = null)
    {
        if (text == null) return null;
        Encoding = Encoding ?? System.Text.Encoding.Unicode;            // If the encoding is not specified use the Unicode
        var textBytes = Encoding.GetBytes(text);                        // Get the bytes according to the encoding
        var textStream = new MemoryStream();                            // Make a stream of to be feeded by zip stream
        var zip = new GZipStream(textStream, CompressionMode.Compress); // Create a zip stream to receive zipped content in textStream
        zip.Write(textBytes, 0, textBytes.Length);                      // Write textBytes into zip stream, then zip will populate textStream
        zip.Close();
        return textStream.ToArray();                                    // Get the bytes from the text stream
    }

    public static string Decompress(byte[] value, Encoding Encoding = null)
    {
        if (value == null) return null;
        Encoding = Encoding ?? System.Text.Encoding.Unicode;                // If the encoding is not specified use the Uncide
        var inputStream = new MemoryStream(value);                          // Create a stream based on input value
        var outputStream = new MemoryStream();                              // Create a stream to recieve output
        var zip = new GZipStream(inputStream, CompressionMode.Decompress);  // Create a stream to decompress inputStream into outputStream
        byte[] bytes = new byte[4096];
        int n;
        while ((n = zip.Read(bytes, 0, bytes.Length)) != 0)                 // While zip results output bytes from input stream
        {
            outputStream.Write(bytes, 0, n);                                // Write the unzipped bytes into output stream
        }
        zip.Close();
        return Encoding.GetString(outputStream.ToArray());                  // Get the string from unzipped bytes
    }
}


Sam Naseri
Software Developer
Blog : http://samondotnet.blgospot.com
GeneralRe: Sharing my code Pin
Thymine20-Mar-12 11:40
Thymine20-Mar-12 11:40 
GeneralRe: Sharing my code Pin
SamNaseri20-Mar-12 12:53
SamNaseri20-Mar-12 12:53 
GeneralRe: Sharing my code Pin
Frankidoze21-Mar-12 6:00
Frankidoze21-Mar-12 6:00 
GeneralThis code will work properly if Pin
Member 28508507-Jun-11 19:16
Member 28508507-Jun-11 19:16 
GeneralThis article is full of bugs, don't use it! Pin
xxbbcc28-May-11 16:51
xxbbcc28-May-11 16:51 
GeneralMy vote of 1 Pin
xxbbcc28-May-11 16:42
xxbbcc28-May-11 16:42 
GeneralMy vote of 1 Pin
djpitagora27-Sep-10 7:04
djpitagora27-Sep-10 7:04 
GeneralRe: My vote of 1 Pin
Frankidoze21-Mar-12 5:50
Frankidoze21-Mar-12 5:50 
GeneralDecompress bug fix Pin
filoteanuadrian9-Apr-10 4:10
filoteanuadrian9-Apr-10 4:10 
GeneralRe: Decompress bug fix Pin
TEST ME26-Apr-11 16:37
TEST ME26-Apr-11 16:37 
GeneralDoesn't work at all Pin
Vikcia26-Mar-10 7:49
Vikcia26-Mar-10 7:49 
GeneralPublic Class CZip .... Pin
Erfan2-Feb-10 19:45
Erfan2-Feb-10 19:45 
GeneralRe: Public Class CZip .... Pin
Nasenbaaer12-Apr-13 6:23
Nasenbaaer12-Apr-13 6:23 
GeneralobjCompressedStream.Length not supported Pin
Upendra Jagdale26-Aug-09 20:17
professionalUpendra Jagdale26-Aug-09 20:17 
GeneralPerformance Improvement/Cleanup Pin
matthias Weiser10-Dec-08 3:34
matthias Weiser10-Dec-08 3:34 
GeneralRe: Performance Improvement/Cleanup Pin
matthias Weiser10-Dec-08 3:48
matthias Weiser10-Dec-08 3:48 
GeneralIn the decompression to string the buffer size is wrong. A decompressed string may be larger than the original data. Pin
elinder91225-Sep-08 10:59
elinder91225-Sep-08 10:59 
GeneralFlush doesn't flush Pin
Richard Birkby8-Sep-08 3:16
Richard Birkby8-Sep-08 3:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.