Introduction
This article presents two methods to compress and decompress string
s 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
:
public static string Zip(string value)
{
byte[] byteArray = new byte[value.Length];
int indexBA = 0;
foreach (char item in value.ToCharArray())
{
byteArray[indexBA++] = (byte)item;
}
System.IO.MemoryStream ms = new System.IO.MemoryStream();
System.IO.Compression.GZipStream sw = new System.IO.Compression.GZipStream(ms,
System.IO.Compression.CompressionMode.Compress);
sw.Write(byteArray, 0, byteArray.Length);
sw.Close();
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
.
public static string UnZip(string value)
{
byte[] byteArray = new byte[value.Length];
int indexBA = 0;
foreach (char item in value.ToCharArray())
{
byteArray[indexBA++] = (byte)item;
}
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);
byteArray = new byte[byteArray.Length];
int rByte = sr.Read(byteArray, 0, byteArray.Length);
System.Text.StringBuilder sB = new System.Text.StringBuilder(rByte);
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!