2

I am tring to write generate a gzipped XML file from a MemoryStream. Here is what I have so far -

XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;

MemoryStream ms = new MemoryStream();
using (XmlWriter writer = XmlWriter.Create(ms, settings))
{
    // CREATE XML
}

Then I want to take that stream, and save it to a compressed file. I've seen many examples using GZipStream, but none exactly match this.

Lucas
  • 3,376
  • 6
  • 31
  • 46
A Bogus
  • 3,852
  • 11
  • 39
  • 58
  • 1
    You might want to look at just controlling your gzip compression at the server level. You can have all xml responses gzip compressed at the IIS level. – Brian Ogden Jul 19 '13 at 21:20

2 Answers2

5

To save a document to a compressed file, you have to create two streams:

using (var fs = File.Create(fileName))
{
    using (var gz = new GZipStream(fs, CompressionMode.Compress))
    {
        doc.Save(gz);
    }
}

It assumes that you've created an XmlDocument. It then calls the XmlDocument.Save(Stream) method.

If you want to write XML directly to a compressed file, you can write:

using (var fs = File.Create(fileName))
{
    using (var gz = new GZipStream(fs, CompressionMode.Compress))
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        using (var writer = XmlWriter.Create(gz, settings))
        {
            // write xml here
        }
    }
}

That's the way that I'd suggest if you just want to write a gzip compressed XML file.

If you really want to go to a MemoryStream first, and then to a compressed file, you create the memory stream as you show in your question, and then you write it like this.

using (var fs = File.Create(fileName))
{
    using (var gz = new GZipStream(fs, CompressionMode.Compress))
    {
        ms.CopyTo(gz);
    }
}

Remember to set ms.Position = 0 before you do the copy.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • Hey Jim, I saw you made a comment in the other anwser, I would rather just take the memory stream, and write it to a compressed file. Maybe I misunderstood your answer. Is that what you were saying to do? One thing that I didn't understand was `doc.Save(gz)` in your answer. You didn't define doc. – A Bogus Jul 22 '13 at 18:35
  • @ABogus: See my updated answer, in particular the second example. – Jim Mischel Jul 22 '13 at 19:30
0

First of all save this to a file

 XmlDocument doc = new XmlDocument();
 doc.Save(writer);

Then use the zip methods to compress it. For compressing

    byte[] b;
using (FileStream f = new FileStream("filename", FileMode.Open))
{
    b = new byte[f.Length];
    f.Read(b, 0, (int)f.Length);
}

using (FileStream f2 = new FileStream(fileName, FileMode.Create))
using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false))
{
    gz.Write(b, 0, b.Length);
}
Ehsan
  • 31,833
  • 6
  • 56
  • 65
  • Hey Ehsan, What is "b" in your gz.Write statment? A byte array, correct? How should it be declared? Do I need to initialize it to anything? Thanks! – A Bogus Jul 22 '13 at 12:48
  • This works, Ehsan, except... when I uncompress the file, it seems I am losing the file type, the fact that is was an XML file is lost. Any idea why? Thanks so much for all your help! – A Bogus Jul 22 '13 at 13:03
  • Nevermind, Ehsan. Turns out I have to name the file like this, fileName.xml.gz to maintain the file name. Thanks again! – A Bogus Jul 22 '13 at 13:06
  • @ABogus: I'm curious why you would want to save the file to disk, read it back, and then save it compressed rather than just saving it compressed in the first place. – Jim Mischel Jul 22 '13 at 13:13
  • Hey Jim, I would like to just compress it in the first place. I would like that solution better if you know how to do it. – A Bogus Jul 22 '13 at 18:32