Link to home
Start Free TrialLog in
Avatar of Brian Bush
Brian BushFlag for United States of America

asked on

UnBZip2 a Stream with SharpZipLib

I needed to compress a stream in memory using SharpZipLib and write out the base64encoded string:
https://www.experts-exchange.com/questions/21864314/BZip2-a-Stream-with-SharpZipLib.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
Avatar of noulouk
noulouk

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.
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
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");
            }
      }
}
ASKER CERTIFIED SOLUTION
Avatar of AGBrown
AGBrown
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Brian Bush

ASKER

Awesome. Thanks for your help.
--brian
Your welcome. Thanks for the points.
No problem. I quite like that byte by byte read actually - it means you can display progress as you go.