Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Converting MemoryStream Content to and from Strings in .NET

Tools Mar 31 12

Working with in-memory streams often involves turning byte data into text and vice versa. The key points are:

  • Always use the same text encoding for writing and reading.
  • Reset or manage the Position of the stream before reading.
  • Be careful when disposing StreamReader/StreamWriter; use leaveOpen when needed so the MemoryStream remains usable.

Below are practical patterns in C# and VB.NET.

Serialize to JSON and read back as a string (C#)

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;

public static class JsonHelpers
{
    public static string SerializeToJsonString<T>(T value)
    {
        using var ms = new MemoryStream();
        var json = new DataContractJsonSerializer(typeof(T));
        json.WriteObject(ms, value);

        ms.Position = 0; // rewind before reading
        using var reader = new StreamReader(ms, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4096, leaveOpen: false);
        return reader.ReadToEnd();
    }
}

// Example
// var text = JsonHelpers.SerializeToJsonString(model);

If you already have a MemoryStream and want a string out of it:

static string ReadAllTextFromMemory(MemoryStream buffer, Encoding? encoding = null)
{
    var enc = encoding ?? Encoding.UTF8;
    long saved = buffer.Position;
    buffer.Position = 0;
    using var reader = new StreamReader(buffer, enc, detectEncodingFromByteOrderMarks: true, bufferSize: 4096, leaveOpen: true);
    string text = reader.ReadToEnd();
    buffer.Position = saved;
    return text;
}

Writing and reading text with MemoryStream (VB.NET)

Imports System.IO
Imports System.Text

Module Module1
    Sub Main()
        Using mem As New MemoryStream()
            ' Keep the stream open when disposing writers/readers
            Using writer As New StreamWriter(mem, Encoding.UTF8, 1024, leaveOpen:=True)
                writer.WriteLine("Hello from VB.NET")
                writer.Flush()
            End Using

            ' Rewind before reading
            mem.Position = 0

            Using reader As New StreamReader(mem, Encoding.UTF8, detectEncodingFromByteOrderMarks:=True, bufferSize:=1024, leaveOpen:=True)
                Dim text = reader.ReadToEnd()
                Console.WriteLine(text)
            End Using
        End Using
    End Sub
End Module

Reading a MemoryStream using the byte array directly

This approach avoids a StreamReader but copies the bytes. It’s simple, but for large buffers, consider reading directly from the stream.

// Encoding must match the bytes inside the stream
string text = Encoding.UTF8.GetString(memoryStream.ToArray());

For slightly less copying (when allowed), you can use the current contents and length:

// Works when the stream is not closed and you accept exposing the internal buffer
string text = Encoding.UTF8.GetString(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);

Read from an arbitrary position and preserve the current cursor (VB.NET)

Imports System.IO
Imports System.Text

Module StreamReadSlice
    Public Function ReadSlice(mem As MemoryStream, Optional offset As Long = 0, Optional enc As Encoding = Nothing) As String
        If enc Is Nothing Then enc = Encoding.UTF8
        Dim original = mem.Position
        mem.Position = Math.Max(0, Math.Min(offset, mem.Length))
        Dim result As String
        Using r As New StreamReader(mem, enc, detectEncodingFromByteOrderMarks:=True, bufferSize:=4096, leaveOpen:=True)
            result = r.ReadToEnd()
        End Using
        mem.Position = original
        Return result
    End Function
End Module

Extensoin method: read entire MemoryStream as text (C#)

using System.IO;
using System.Text;

public static class MemoryStreamReadExtensions
{
    public static string ReadAllText(this MemoryStream stream, Encoding? encoding = null, long start = 0)
    {
        var enc = encoding ?? Encoding.UTF8;
        long saved = stream.Position;
        if (start >= 0) stream.Position = start;
        using var reader = new StreamReader(stream, enc, detectEncodingFromByteOrderMarks: true, bufferSize: 4096, leaveOpen: true);
        string text = reader.ReadToEnd();
        stream.Position = saved;
        return text;
    }
}

Usage:

using var ms = new MemoryStream();
using var w = new StreamWriter(ms, Encoding.UTF8, 1024, leaveOpen: true);
w.Write("sample");
w.Flush();
Console.WriteLine(ms.ReadAllText());

Extension methods to write lines and dump to console (C#)

using System;
using System.IO;
using System.Text;

public static class MemoryStreamWriteExtensions
{
    public static void AppendLine(this MemoryStream stream, string line, Encoding? encoding = null, bool flush = false)
    {
        var enc = encoding ?? Encoding.UTF8;
        byte[] data = enc.GetBytes(line + Environment.NewLine);
        lock (stream) // optional: synchronize when accessed from multiple threads
        {
            stream.Write(data, 0, data.Length);
            if (flush) stream.Flush();
        }
    }

    public static void DumpToConsole(this MemoryStream stream, Encoding? encoding = null)
    {
        var enc = encoding ?? Encoding.UTF8;
        lock (stream)
        {
            long saved = stream.Position;
            stream.Position = 0;
            using var r = new StreamReader(stream, enc, detectEncodingFromByteOrderMarks: true, bufferSize: 4096, leaveOpen: true);
            var text = r.ReadToEnd();
            stream.Position = saved;
            if (!string.IsNullOrEmpty(text))
                Console.WriteLine(text);
        }
    }
}

End-to-end example: serialize to JSON, convert to string, reconstruct stream, and deserialize (C#)

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;

[DataContract]
public class Contact
{
    [DataMember] public int Id { get; set; }
    [DataMember] public string Name { get; set; } = string.Empty;
    [DataMember] public DateTime Created { get; set; }
    [DataMember] public List<Phone> Phones { get; set; } = new();
}

[DataContract]
public class Phone
{
    [DataMember] public PhoneKind Kind { get; set; }
    [DataMember] public string Number { get; set; } = string.Empty;
}

public enum PhoneKind { Home = 1, Mobile = 2 }

public static class JsonRoundtrip
{
    public static string MemoryStreamToString(MemoryStream ms, Encoding? enc = null)
    {
        var e = enc ?? Encoding.UTF8;
        ms.Position = 0;
        using var reader = new StreamReader(ms, e, detectEncodingFromByteOrderMarks: true, bufferSize: 4096, leaveOpen: true);
        return reader.ReadToEnd();
    }

    public static MemoryStream StringToMemoryStream(string s, Encoding? enc = null)
    {
        var e = enc ?? Encoding.UTF8;
        var bytes = e.GetBytes(s);
        return new MemoryStream(bytes, 0, bytes.Length, writable: false, publiclyVisible: true);
    }

    public static void Demo()
    {
        var model = new Contact
        {
            Id = 7,
            Name = "Sample",
            Created = DateTime.UtcNow,
            Phones = new List<Phone>
            {
                new Phone { Kind = PhoneKind.Home,   Number = "555-0100" },
                new Phone { Kind = PhoneKind.Mobile, Number = "555-0200" }
            }
        };

        var serializer = new DataContractJsonSerializer(typeof(Contact));
        using var outbound = new MemoryStream();
        serializer.WriteObject(outbound, model);

        string json = MemoryStreamToString(outbound);
        Console.WriteLine(json);

        using var inbound = StringToMemoryStream(json);
        inbound.Position = 0;
        var model2 = (Contact)serializer.ReadObject(inbound)!;

        Console.WriteLine($"{model2.Id} {model2.Name} {model2.Created:yyyy-MM-dd}");
    }
}

Simple byte[] → MemoryStream → string (C#)

var data = Encoding.ASCII.GetBytes("Alpha - Beta");
using var ms = new MemoryStream(data, writable: false);
using var reader = new StreamReader(ms, Encoding.ASCII, detectEncodingFromByteOrderMarks: false, bufferSize: 1024, leaveOpen: false);
string s = reader.ReadToEnd();

StreamReader with ReadToEnd (C#)

using var ms = new MemoryStream();
using var writer = new StreamWriter(ms, Encoding.UTF8, 1024, leaveOpen: true);
writer.Write("example");
writer.Flush();

ms.Position = 0;
using var reader = new StreamReader(ms, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4096, leaveOpen: true);
string text = reader.ReadToEnd();

VB.NET extension: read entire MemoryStream and restore position

Imports System.IO
Imports System.Runtime.CompilerServices
Imports System.Text

Public Module MemoryStreamExtensions
    <Extension>
    Public Function ReadAll(ByVal mem As MemoryStream, Optional ByVal enc As Encoding = Nothing) As String
        If enc Is Nothing Then enc = Encoding.UTF8
        Dim pos = mem.Position
        mem.Position = 0
        Dim value As String
        Using r As New StreamReader(mem, enc, detectEncodingFromByteOrderMarks:=True, bufferSize:=4096, leaveOpen:=True)
            value = r.ReadToEnd()
        End Using
        mem.Position = pos
        Return value
    End Function
End Module

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Capturing Android Screenshots and Screen Recordings with ADB

Two practical ways to grab images and videos from an Android device: Mirror the phone display to a computer and use desktop tools for screenshots and GIFs Use ADB commands (no UI mirroring required)...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.