2

I do not seem to be able to write text via StreamWriter to a to be newly created zip file (not gzip). I use SharpZipLib and do not quite comprehend how to get it to work. DJ Kraze helped me with streaming content from a zipped text file to StreamReader, I now try the opposite. I do not want to create a csv file first and then compress the finalized file but like to stream text directly to a to be created csv within the zip container. Is that possible? Below a snippet I use for getting a stream that I can use with StreamReader, it just gives an idea what I am looking for, just that this time I like to get a stream to be used with StreamWriter.

public static Stream GetZipInputFileStream(string fileName)
{
    ZipInputStream zip = new ZipInputStream(File.OpenRead(fileName));
    FileStream filestream = 
        new FileStream(fileName, FileMode.Open, FileAccess.Read);
    ZipFile zipfile = new ZipFile(filestream);
    ZipEntry item;

    if ((item = zip.GetNextEntry()) != null)
    {
        return zipfile.GetInputStream(item);
    }
    else
    {
        return null;
    }
}

Here is how I use it, which I essentially look for but the other way around (StreamWriter -> new csv file in new zip container):

using (StreamReader streamReader = Path.GetExtension(fileName).ToUpper().Equals(".ZIP") ? new StreamReader(FileOperations.GetZipInputFileStream(fileName)) : new StreamReader(fileName))
            {
Matt
  • 7,004
  • 11
  • 71
  • 117

2 Answers2

0

The second example here addresses writing a stream directly to a zip file from SharpZipLib. Give that a quick look and let us know how it works for you.

Edit: Since the link is being problematic, below is the example from the wiki.

public void UpdateZipInMemory(Stream zipStream, Stream entryStream, String entryName) 
{

    // The zipStream is expected to contain the complete zipfile to be updated
    ZipFile zipFile = new ZipFile(zipStream);

    zipFile.BeginUpdate();

    // To use the entryStream as a file to be added to the zip,
    // we need to put it into an implementation of IStaticDataSource.
    CustomStaticDataSource sds = new CustomStaticDataSource();
    sds.SetStream(entryStream);

    // If an entry of the same name already exists, it will be overwritten; otherwise added.
    zipFile.Add(sds, entryName);

    // Both CommitUpdate and Close must be called.
    zipFile.CommitUpdate();

    // Set this so that Close does not close the memorystream
    zipFile.IsStreamOwner = false;
    zipFile.Close();

    // Reposition to the start for the convenience of the caller.
    zipStream.Position = 0;
}

And the supporting data structure

public class CustomStaticDataSource : IStaticDataSource
{
    private Stream _stream;

    // Implement method from IStaticDataSource
    public Stream GetSource() { return _stream; }

    // Call this to provide the memorystream
    public void SetStream(Stream inputStream) 
    {
        _stream = inputStream;
        _stream.Position = 0;
    }
}

There's an example of calling that code if you can get through to the site.

TimW
  • 73
  • 1
  • 6
  • Odd. Sorry about that. Try pasting this: http://wiki.sharpdevelop.net/SharpZipLib_Updating.ashx – TimW Feb 24 '12 at 18:17
  • Thanks for the code, but I guess I am still lost. I do not see how it gives me access to stream to which I can write through StreamWriter. I need StreamWriter sw = new StreamWriter(-> <-) so that I can simply use sw.WriteLine("Hello World") which in turn streams the string to the newly created csv file within a created zip container if that makes any sense. I believe my code snippet is a very elegant way to retrieve a Stream object to be used when extracting data from a file within zip container. I just need it the other way around. – Matt Feb 24 '12 at 19:15
  • I edited and added how I use my snippet in combination with StreamReader. I look for a similarly elegant solution to use with StreamWriter. – Matt Feb 24 '12 at 19:29
  • TimW, this code does not provide a solution to my question. While it demonstrates how to write a completed(!) stream to an existing complete(!) zip Stream it does not address how a stream can be provided that StreamWriter can use to write directly into the zip container. – Matt Feb 25 '12 at 10:53
  • Is it important that you write a partial file to the zip stream? Or are you just trying to avoid writing the file to disk? If it's the latter, you could point the StreamWriter at a MemoryStream, use the StreamWriter to write your file, then save the underlying stream to the zip stream once you're done. – TimW Feb 27 '12 at 14:16
  • Tim, its important to write a partial stream to the zip stream as complete streams are far too large to process at once. Thats why I like the way to read a stream from a zip stream partially as demonstrated in my original question. I just dont see a way to write in the same way. Ideally I like to use a StreamWriter sw object as sw.WriteLine(whateverString) and sw streams through a buffer each of those rows to the zip stream. I believe the library does not allow for this at this point in time from what I have seen. – Matt Feb 28 '12 at 05:45
0

I ended up dumping SharpZipLib for this purpose and instead went the more space intensive route of first unzipping all files in the zip container, processing the data and then moving the files back into the zip container. The problem I faced, as described above was that I could not read any of the files in the container at once due to their large size. It would be nice to see a zip library that may be able to handle partial stream writing into the container in the future but for now I did not see a way to get it done with SharpZipLib.

Matt
  • 7,004
  • 11
  • 71
  • 117