UnBZip2 a Stream with SharpZipLib

I needed to compress a stream in memory using SharpZipLib and write out the base64encoded string:
http://www.experts-exchange.com/Programming/Programming_Languages/C_Sharp/Q_21864314.html

Now I need to do the reverse.

I want to:
1. open a text file that contains a base64encoded string
2. decode it
3. UnBZip2 it
4. write out the file.

Simple enough?

--brian
LVL 6
Brian BushSolutions ArchitectAsked:
Who is Participating?
 
AGBrownConnect With a Mentor Commented:
Here's the read from file/write to file/read from file/write to file version

using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using ICSharpCode.SharpZipLib.BZip2;

namespace ConsoleApplication1
{

      class Program
      {
            const string FILE_PATH = @"C:\test.txt";
            const string BZIP_PATH = @"C:\test2.bzip2";
            const string OUT_PATH = @"C:\test2.out.txt";
            static void Main(string[] args)
            {
                  CheckFileExists();

                  byte[] compressedBytes = null;


                  //       open the file into a stream
                  using (FileStream fs = File.OpenRead(FILE_PATH))
                  {
                        //      compress onto a memory stream
                        using (MemoryStream mem = new MemoryStream())
                        {
                              //      now create the compression stream based on the memory stream
                              using (BZip2OutputStream comp = new BZip2OutputStream(mem, 4096))
                              {
                                    int singleByte = fs.ReadByte();
                                    while (singleByte != -1)
                                    {
                                          comp.WriteByte((byte)singleByte);
                                          singleByte = fs.ReadByte();
                                    }
                              }      // the using statement ensures a flush, finalize and close

                              //      now we write the memorystream to the interim byte array to show there are now hidden tricks
                              compressedBytes = mem.ToArray();
                        }
                  }

                  //      Write to file
                  using (StreamWriter sw = new StreamWriter(BZIP_PATH, false, Encoding.UTF8))
                  {
                        sw.Write(Convert.ToBase64String(compressedBytes));
                  }

                  //      END COMPRESSION, BEGIN DECOMPRESSION

                  byte[] receivedCompressedBase64;

                  //      Read from file
                  using (StreamReader sr = File.OpenText(BZIP_PATH))
                  {
                        string strCompressed64 = sr.ReadToEnd();
                        receivedCompressedBase64 = Convert.FromBase64String(strCompressed64);
                  }

                  //      decompress to a memory stream using a memory stream to access the byte array
                  using (FileStream decomp = File.Open(OUT_PATH, FileMode.Create)) // target memory stream to get the decompressed data
                  {
                        using (MemoryStream comp = new MemoryStream(receivedCompressedBase64)) // memory stream to read from the byte array
                        {
                              //      now create the decompression stream based on the input memory stream
                              using (BZip2InputStream bzdecomp = new BZip2InputStream(comp))
                              {
                                    //      write from the decompression stream to the target stream one byte at a time
                                    int singleByte = bzdecomp.ReadByte();
                                    while (singleByte != -1)
                                    {
                                          decomp.WriteByte((byte)singleByte);
                                          singleByte = bzdecomp.ReadByte();
                                    }
                              }      // the using statement ensures a flush, finalize and close
                        }
                  }
            }
            private static void CheckFileExists()
            {
                  if (!File.Exists(FILE_PATH))
                        throw new FileNotFoundException("Could not find source file C:\test.txt");
            }
      }
}
0
 
nouloukCommented:
Hi brian,

Something like this:

System.IO.StreamReader t = new System.IO.StreamReader("c:\test.bzip2");
            string ss= t.ReadToEnd();
            byte[] compressedBytes=Convert.FromBase64String(ss);
            System.IO.MemoryStream comp = new System.IO.MemoryStream(compressedBytes);

            ICSharpCode.SharpZipLib.BZip2.BZip2InputStream b = new ICSharpCode.SharpZipLib.BZip2.BZip2InputStream(comp);
            byte[] decompBytes = new byte[b.Length];
            b.Read(decompBytes, 0, (int)b.Length);

            System.IO.FileStream fs = new System.IO.FileStream("c:\test.txt", System.IO.FileMode.Create);
            fs.Write(decompBytes, 0, decompBytes.Length);

Hope this helps.
0
 
AGBrownCommented:
Yeah, what you need is basically the same as the part of the code from the:

byte[] receivedCompressedBase64 = Convert.FromBase64String(strInterimStorage);

onwards, but using
               //      open the file into a stream
               using (FileStream fs = File.OpenRead(FILE_PATH))
               {
                    //     and read into a byte array
                    receivedCompressedBase64 = new byte[fs.Length];
                    fs.Read(receivedCompressedBase64 , 0, (int)fs.Length);
               }

to read in the bytes and then writing out a file. Again, I would use a "using" with the output FileStream, or at least ensure that you flush and close the FileStream.

The main problem is again going to be the truncation.

An alternative, if you are just worried about storing in a file and not about the Base64 format, would be:
      using (FileStream readStream = File.OpenRead(FILE_PATH))
      {
            using (FileStream compStream = File.Open(BZIP_PATH, FileMode.Create))
            {
                  BZip2.Compress(readStream, compStream, 4096);
            }
      }
                  
      using (FileStream readStream = File.OpenRead(BZIP_PATH))
      {
            using (FileStream decompStream = File.Open(OUT_PATH, FileMode.Create))
            {
                  BZip2.Decompress(readStream, decompStream);
            }
      }

A
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
AGBrownCommented:
This gets round all the problems I mentioned. Write to file version to follow.

There is a key line in here that will make it work/break, and that is the decomp.Seek(0, SeekOrigin.Begin); line. Try taking that out and see what happens. Basically, as the stream position is at the end of the decompressed bytes that have been written, the byte[] decompressedBytes will not be filled with anything.

using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using ICSharpCode.SharpZipLib.BZip2;

namespace ConsoleApplication1
{

      class Program
      {
            const string FILE_PATH = @"C:\test.txt";
            const string BZIP_PATH = @"C:\test2.bzip2";
            const string OUT_PATH = @"C:\test.out.txt";
            static void Main(string[] args)
            {
                  CheckFileExists();

                  byte[] compressedBytes = null;

                  //       open the file into a stream
                  using (FileStream fs = File.OpenRead(FILE_PATH))
                  {
                        //      compress onto a memory stream
                        using (MemoryStream mem = new MemoryStream())
                        {
                              //      now create the compression stream based on the memory stream
                              using (BZip2OutputStream comp = new BZip2OutputStream(mem, 4096))
                              {
                                    int singleByte = fs.ReadByte();
                                    while (singleByte != -1)
                                    {
                                          comp.WriteByte((byte)singleByte);
                                          singleByte = fs.ReadByte();
                                    }
                              }      // the using statement ensures a flush, finalize and close

                              //      now we write the memorystream to the interim byte array to show there are now hidden tricks
                              compressedBytes = mem.ToArray();
                        }
                  }

                  /* DISPLAY RESULTS */
                  //      COnvert the bytes to a string
                  string strInterimStorage = Convert.ToBase64String(compressedBytes);

                  Console.WriteLine("Compressed string (base64)");
                  Console.WriteLine(strInterimStorage);
                  /* END DISPLAY RESULTS */

                  byte[] receivedCompressedBase64 = Convert.FromBase64String(strInterimStorage);
                  byte[] decompressedBytes;
                  //      decompress to a memory stream using a memory stream to access the byte array
                  using (MemoryStream decomp = new MemoryStream())
                  {
                        using (MemoryStream comp = new MemoryStream(receivedCompressedBase64))
                        {
                              //      now create the decompression stream based on the input memory stream
                              using (BZip2InputStream bzdecomp = new BZip2InputStream(comp))
                              {
                                    int singleByte = bzdecomp.ReadByte();
                                    while (singleByte != -1)
                                    {
                                          decomp.WriteByte((byte)singleByte);
                                          singleByte = bzdecomp.ReadByte();
                                    }
                              }      // the using statement ensures a flush, finalize and close
                        }
                        decomp.Flush();
                        decomp.Seek(0, SeekOrigin.Begin);
                        decompressedBytes = new byte[decomp.Length];
                  
                        decomp.Read(decompressedBytes, 0, (int)decomp.Length);
                  }

                  string strFinal = Encoding.ASCII.GetString(decompressedBytes);
                  Console.WriteLine("Decompressed string (base64)");
                  Console.WriteLine("[{0}]", strFinal);
                  Console.ReadLine();
            }
            private static void CheckFileExists()
            {
                  if (!File.Exists(FILE_PATH))
                        throw new FileNotFoundException("Could not find source file C:\test.txt");
            }
      }
}
0
 
Brian BushSolutions ArchitectAuthor Commented:
Awesome. Thanks for your help.
--brian
0
 
nouloukCommented:
Your welcome. Thanks for the points.
0
 
AGBrownCommented:
No problem. I quite like that byte by byte read actually - it means you can display progress as you go.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.