I need to write a unit test for a method that takes a stream which comes from a text file. I would like to do do something like this:
Stream s = GenerateStreamFromString("a,b \n c,d");
This question is related to
c#
unit-testing
string
stream
If you need to change the encoding I vote for @ShaunBowe's solution. But every answer here copies the whole string in memory at least once. The answers with ToCharArray
+ BlockCopy
combo do it twice.
If that matters here is a simple Stream
wrapper for the raw UTF-16 string. If used with a StreamReader
select Encoding.Unicode
for it:
public class StringStream : Stream
{
private readonly string str;
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => str.Length * 2;
public override long Position { get; set; } // TODO: bounds check
public StringStream(string s) => str = s ?? throw new ArgumentNullException(nameof(s));
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
Position = offset;
break;
case SeekOrigin.Current:
Position += offset;
break;
case SeekOrigin.End:
Position = Length - offset;
break;
}
return Position;
}
private byte this[int i] => (i & 1) == 0 ? (byte)(str[i / 2] & 0xFF) : (byte)(str[i / 2] >> 8);
public override int Read(byte[] buffer, int offset, int count)
{
// TODO: bounds check
var len = Math.Min(count, Length - Position);
for (int i = 0; i < len; i++)
buffer[offset++] = this[(int)(Position++)];
return (int)len;
}
public override int ReadByte() => Position >= Length ? -1 : this[(int)Position++];
public override void Flush() { }
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override string ToString() => str; // ;)
}
And here is a more complete solution with necessary bound checks (derived from MemoryStream
so it has ToArray
and WriteTo
methods as well).
Add this to a static string utility class:
public static Stream ToStream(this string str)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(str);
writer.Flush();
stream.Position = 0;
return stream;
}
This adds an extension function so you can simply:
using (var stringStream = "My string".ToStream())
{
// use stringStream
}
I think you can benefit from using a MemoryStream. You can fill it with the string bytes that you obtain by using the GetBytes method of the Encoding class.
Use the MemoryStream
class, calling Encoding.GetBytes
to turn your string into an array of bytes first.
Do you subsequently need a TextReader
on the stream? If so, you could supply a StringReader
directly, and bypass the MemoryStream
and Encoding
steps.
Another solution:
public static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
}
Modernized and slightly modified version of the extension methods for ToStream
:
public static Stream ToStream(this string value) => ToStream(value, Encoding.UTF8);
public static Stream ToStream(this string value, Encoding encoding)
=> new MemoryStream(encoding.GetBytes(value ?? string.Empty));
Modification as suggested in @Palec's comment of @Shaun Bowe answer.
I used a mix of answers like this:
public static Stream ToStream(this string str, Encoding enc = null)
{
enc = enc ?? Encoding.UTF8;
return new MemoryStream(enc.GetBytes(str ?? ""));
}
And then I use it like this:
String someStr="This is a Test";
Encoding enc = getEncodingFromSomeWhere();
using (Stream stream = someStr.ToStream(enc))
{
// Do something with the stream....
}
public Stream GenerateStreamFromString(string s)
{
return new MemoryStream(Encoding.UTF8.GetBytes(s));
}
A good combination of String extensions:
public static byte[] GetBytes(this string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
public static Stream ToStream(this string str)
{
Stream StringStream = new MemoryStream();
StringStream.Read(str.GetBytes(), 0, str.Length);
return StringStream;
}
Here you go:
private Stream GenerateStreamFromString(String p)
{
Byte[] bytes = UTF8Encoding.GetBytes(p);
MemoryStream strm = new MemoryStream();
strm.Write(bytes, 0, bytes.Length);
return strm;
}
We use the extension methods listed below. I think you should make the developer make a decision about the encoding, so there is less magic involved.
public static class StringExtensions {
public static Stream ToStream(this string s) {
return s.ToStream(Encoding.UTF8);
}
public static Stream ToStream(this string s, Encoding encoding) {
return new MemoryStream(encoding.GetBytes(s ?? ""));
}
}
Source: Stackoverflow.com