/Images/MainImage/Marcus Hammarberg.jpg finns inte.

Inlägg December 2008

2008-12-15 15:56

Compress a string with zip

[UPDATE START]

We found a nasty performance bug in the code below. The DeCompress-method copies a string for each turn in the loop. That is a classic problem that creates a new copy of the string for each row. That became a major problem for a 3.8 Mb string...

I have now updated the code to use the System.Text.StringBuilder object instead. That took down the speed to about a tenth. Sorry that I didn't catch that...

[UPDATED STOP]

We had a quite special need the other day; we wanted to compress a part of our request, namely a XML-string that was sent to us.

Most of the examples I found on the net showed how to compress the content of a file. But here is the code that compress a string. The code uses ICSharpCode.SharpZipLib. Here you go:

/// <summary>
/// Compress strings with ICSharpCode.SharpZipLib
/// </summary>
public class StringZipper
{
    public static string Compress(string uncompressedString)
    {
        byte[] bytData = System.Text.Encoding.UTF8.GetBytes(uncompressedString);
        MemoryStream ms = new MemoryStream();
        Stream s = new DeflaterOutputStream(ms);
        s.Write(bytData, 0, bytData.Length);
        s.Close();
        byte[] compressedData = (byte[])ms.ToArray();
        return System.Convert.ToBase64String(compressedData, 0, compressedData.Length);
    }

 

    public static string DeCompress(string compressedString)
    {
        StringBuilder uncompressedString = new StringBuilder();
        int totalLength = 0;
        byte[] bytInput = System.Convert.FromBase64String(compressedString); ;
        byte[] writeData = new byte[4096];
        Stream s2 = new InflaterInputStream(new MemoryStream(bytInput));
        while (true)
        {
            int size = s2.Read(writeData, 0, writeData.Length);
            if (size > 0)
            {
                totalLength += size;
                uncompressedString.Append(System.Text.Encoding.UTF8.GetString(writeData, 0, size));
            }
            else
            {
                break;
            }
        }
        s2.Close();
        return uncompressedString.ToString();
    }
}

And here is how to call it:

// Compress the string
                    string orgString = "Hello compression with åäö.";
                    //orgString = File.ReadAllText(args[0]);

                    Stopwatch sw = new Stopwatch();
                    sw.Start();
                    string compressedString = StringZipper.Compress(orgString);
                    sw.Stop();
                    string compressTime = sw.ElapsedMilliseconds.ToString();

                    // Decompress the string
                    sw.Reset(); sw.Start();
                    string decompressedString = StringZipper.DeCompress(compressedString);
                    sw.Stop();
                    string decompressTime = sw.ElapsedMilliseconds.ToString();

                    if (orgString == decompressedString)
                        Console.WriteLine("SAME");
                    else
                        Console.WriteLine("DIFFER");

                    // Show some nice statistics
                    decimal ratio = (decimal)compressedString.Length / (decimal)orgString.Length;
                    Console.WriteLine(string.Format("Orignal string was: {0} chars", orgString.Length));
                    Console.WriteLine(string.Format("Compressed string was: {0} chars", compressedString.Length));
                    Console.WriteLine(string.Format("DeCompressed string was: {0} chars ", decompressedString.Length));
                    Console.WriteLine(string.Format("Compression ratio {0}", ratio));
                    Console.WriteLine(string.Format("The compression took {0} ms, DeCompression took {1} ms", compressTime, decompressTime));

I should point out two things;

  • For short strings the compressed string might actually be longer than the original.
  • It's not very good to store the result of the compression as a string (as done by System.Convert.ToBase64String), but it's quite nice to have for serialization.


Postad av Marcus Hammarberg

Kommentarer (1)



2008-12-15 08:46

Cheat-sheet for Resharper 4.0

Found this paper with the (default) keymapping for Resharper. Here is also some demos etc.

Finally there is an update to ReSharper to 4.1 - hopefully it will solve my stability problems. I'll keep you posted...


Postad av Marcus Hammarberg

Kommentarer (0)



2008-12-11 14:28

UTA058: The test engine cannot run tests in the assembly for out integration test

We have a done a MsTest-dll that contain our integration tests that is run after each deploy to our daily build environment.

However on our new build server we ran into problems with the following error message.

"UTA058: The test engine cannot run tests in the assembly"

OK - it seems that you need to configure .NET Framework to allow running assemblies from network shared.

I found this description on how to solve it (potentially the longest URL on the net ;).

But we ran into more trouble... The .NET Framework 2.0 Configuration was no where to be found. As it seems that tool disappears when the .NET Framework 2.0 SDK is installed. Where it disappeared to is a another question that I haven't found an answer to.

However the great description also told us how to handle the problem on the command prompt, with the caspol-tool.

To make a long story short - this command solved the problem on our build machine. Good enough for us:

caspol -machine -addgroup 1 -url \\[machine]\Drops\* FullTrust -name FileW


Postad av Marcus Hammarberg

Kommentarer (0)



2008-12-10 15:32

SOAP UI - a great way to do integration tests for services

Just found this tool - or actually I've used but missed it's greatness...

The SoapUI can be used to automatically generate clients to access web services. But furthermore it can be used to test web services. With the tool you can generate test request and setup the expected response. This is setup via a nice GUI.

The requests and responses can then be run, in sequence or one by one.

What a great way to do integration tests for a service. Just imagine - you have 100 pre-built request/response-files and just run them (from the command prompt as part of you nightly build of course).

Since not much coding skills are required you can easily put the SoapUI  in the hands of a tester and maintain the requests/responses as checked in files.

Now we just need to find a way to run the test against WCF services. We can always use basicHttpBinding of course... have to think about it.


Postad av Marcus Hammarberg

Kommentarer (0)   Kategorier:  .NET    Agile    TDD



2008-12-09 14:07

Working directory for Build Agents and building different branches

We have been chasing a strange problem for a few days now. The scenario is as follows;

We created a new TFS build server, that is - we set up the build service on a new server. In our TFS Source control we had two branches with a build definition for each. Finally we set up a Build Agent for the new server via Visual Studio Team System.

But the builds failed! With error message "The path [path] is already mapped in workspace [workspace]"

We didn't get why until we checked a property on the build agent; Working Directory. This can be set by right-clicking on the Builds-folder in Team Explorer, choosing the agent and the Edit.

On the Build Agent Properties page there is a WorkingDirectory-textbox. This dictates where the agent should build. However - what not is shown is that you can use a variable in the path: $(BuildDefinitionPath).

Since our build script uses relative paths it was very important that the path looked the same in-different of the build definition. That is we wanted a separate build folder for each build. The $(BuildDefinitionPath) at the end of the WorkingDirectory-property of the build agent solved it!


Postad av Marcus Hammarberg

Kommentarer (0)



2008-12-08 12:36

MSBuild sidekicks

This tool, MSBuild Sidekick, looks quite promising. It's a graphical editor with which you build MSBuild project files.

I am always quite skeptical to tools when you "draw code" that you as easily can write. But this tools seems to hold some very useful features. I'll try to lab with it when I get the chance.


Postad av Marcus Hammarberg

Kommentarer (0)



2008-12-01 23:28

AddressFilter mismatch at the EndpointDispatcher

The complete error message was: "The message with To '[my service address]' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher."

We got this message when we deployed our services to the production environment. In this environment we first encounter BIG-IP and clustering. And that's when we hit this brick wall.

The scenario was that BIG-IP had one DNS-name/Ip-address that "forwarded" request to two different servers. However when we accessed the servers with wsHttpBinding we ran into trouble and the above mentioned error message.

The strange thing was that it worked fine with basicHttpBinding, which puzzled us for a while.

Well, thanks to the excellent knowledge in the Avega Microsoft community, we got an answerer in matter of minutes.

As this post points out you can handle the problem by setting the AddressFilterMode to Any, which basic means - ignore addressfiltering.

As far as I understand WCF matches the address property for the client and the server and if it doesn't match (according to AddressFilterMode) the above mentioned error message is thrown.

And for the strange behavior that basicHttpBinding worked it must have to do with that basicHttpBinding doesn't care about that kind of matching. I believe that it has to do with WS-Addressing and that is not a part of basicHttpBinding.

I love to be challenged about this - this is just what we figured out in the project.

Thanks to all that helped us solve this.


Postad av Marcus Hammarberg

Kommentarer (1)   Kategorier:  .NET    WCF    Life of a consultant

  RSS Feed

Marcus Hammarberg

I am a consultant with Avega working with Microsoft, .NET, system design and agile system development. When i am not working most of my time is taken up by the Salvation Army and playing my instrument, the euphonium. I am married to Elin since july 2006 and we are living in the middle of Stockholm.. In january 2008 our son Albert was born and have taken a prominent place in our hearts and lives.


Kontakt