1

I am currently rewriting a few PowerShell modules in C#, primarily to learn the language and get a grip on C# development. So far it has been going really well, with some 20 functions rewritten and tested.

One I'm stuck on is compressing a GZip string. I've managed to use functions written by others to complete the task, but I was (and still am) unable to directly translate my PowerShell function.

Original PowerShell code:

$ms = New-Object System.IO.MemoryStream
$cs = New-Object System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Compress)
$sw = New-Object System.IO.StreamWriter($cs)
$sw.Write($StringToCompress)
$sw.Close();
[System.Convert]::ToBase64String($ms.ToArray()) | Out-File $FilePath -Force | Out-Null
$cs.Close();
$ms.Close();

C# equivalent (Ignore void, was testing in LINQPad):

public static void CompressString(string stringToCompress)
{
    var memoryStream = new MemoryStream();
    var compression = new GZipStream(memoryStream, CompressionMode.Compress, true);
    var streamWriter = new StreamWriter(compression);

    Console.WriteLine("String to compress: " + stringToCompress);

    streamWriter.Write(stringToCompress);

    Console.WriteLine("Base64 encoded compressed string: " + 
    Convert.ToBase64String(memoryStream.ToArray()));
}

The PowerShell code works perfectly, yet the C# returns nothing. Why is this, as I believe my 'translation' is correct?

enter image description here

Just a reminder, I have fixed my issue with help from another, but am now researching why the above did not work.

2
  • 1
    $sw.Close() causes the stream writer to flush its buffer, but in the C# version you never close it - so by the time you call memoryStream.ToArray() there's no guarantee the writer has actually completed the write to the underlying stream Commented Jun 3, 2020 at 22:44
  • Goodness me... I thought the close method was just for clean-up purposes, I completely ignored it's position in the execution order. Thank you so much, I can finally get that out of my head. Time to read up on Streamwriter... Commented Jun 3, 2020 at 22:59

1 Answer 1

1

As mentioned in the comments, there's a slight difference between your two examples. The PowerShell version works because $sw.Close() causes the stream writer to flush its buffer before closing.

In the C# version you never close it - so by the time you call memoryStream.ToArray() there's no guarantee the writer has actually completed the write to the underlying stream.

The idiomatic approach in C# is to leverage using() statements for IDisposable resources, like so:

Console.WriteLine("String to compress: " + stringToCompress);
using(var memoryStream = new MemoryStream())
{
    using(var compression = new GZipStream(memoryStream, CompressionMode.Compress, true))
    using(var streamWriter = new StreamWriter(compression))
    {
        streamWriter.Write(stringToCompress);
    }

    Console.WriteLine("Base64 encoded compressed string: " + 
        Convert.ToBase64String(memoryStream.ToArray()));
}

In the above example, the streamWriter and compression stream will have been disposed of by the time you read from the memory stream, and by the time you return from the method the memoryStream will also be automatically disposed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.