Arbiter
Arbiter

Reputation: 470

Rewriting PowerShell functions in C#

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.

Upvotes: 1

Views: 199

Answers (1)

Mathias R. Jessen
Mathias R. Jessen

Reputation: 175085

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.

Upvotes: 1

Related Questions