Walks like a stream, talks like a stream

The whole reason I started this blog was to share my thoughts/ideas, and I almost never post to it. Well, that’s all going to change. Right now.

Here’s an idea I had: there are a lot of APIs out there (including parts of .NET) that involve saving/loading to/from files, and these APIs typically have functions like this:

public void Save(Stream stream);
public void Save(string filePath);

There’s something interesting here. If you are a developer using this API, you can either hand data (in the form of a Stream) directly to the API, or tell the API where to find the data. This seems like a perfectly suitable set of options in most cases, particularly when we’re talking about big, unwieldy files containing a lot of data. But occasionally you might be dealing with a small amount of data, and you don’t really want to go through the hassle of reading, writing, or otherwise dealing in any way with an actual file on your PC. For instance, you might prefer to call the API’s Save method and have it just write to a string. Why not? Or perhaps the API requires that you call some Load method, and you’d like to just put the important data in a string—not a file—to which I say, again: why not?

So this was the thinking behind two little classes I just wrote, ImmutableStreamEmulator and MutableStreamEmulator. From the names you can probably guess what they accomplish: an ImmutableStreamEmulator wraps a string and allows code to read it as if it were a Stream, while a MutableStreamEmulator wraps a StringBuilder and allows code to read/write to it, again, just like a Stream. Simple idea, right?

Source code:
MutableStreamEmulator
ImmutableStreamEmulator

The finishing touch on all this is to make these classes immediately accessible via extension methods on string and StringBuilder. Here they are:

public static Stream AsStream(this string @string) {
    return new ImmutableStreamEmulator(@string);
}

public static Stream AsStream(this StringBuilder stringBuilder) {
    return new MutableStreamEmulator(stringBuilder);
}

Now, remember that API that only let me call Save on a Stream or a string which pointed me to a file path? Check it out: now I could just make it save directly to my StringBuilder:

var data = new StringBuilder();

using (var emulatedFile = data.AsStream())
    API.Save(emulatedFile);

// behold! now I have the contents of the "file" in a string
string emulatedFileContents = data.ToString();

// I can therefore also load the "file" with the API
using (var emulatedFile = emulatedFileContents.AsStream())
    API.Load(emulatedFile);

Pretty handy, right? No?

Note that these classes are totally unnecessary in cases where the API allows you to save/load using a TextWriter and TextReader (typically in the form of a StreamWriter and StreamReader). That’s what the StringWriter and StringReader classes are for! These classes are specifically for when an API only wants to deal with Stream objects.

Advertisements

2 thoughts on “Walks like a stream, talks like a stream

  1. Sky says:

    Seems quite handy in some very specific scenarios. Am putting this in my membank for future use.

    • Daniel says:

      Ha, now that someone’s actually read and commented on this, I feel compelled to offer a disclaimer: when I wrote this code, I had literally never heard of the System.IO.MemoryStream class, which could obviously be used for roughly the same purpose. That said, I still think it’s really handy to be able to go straight from a System.String or a System.Text.StringBuilder to a Stream-like object.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: