Как создать поток из строки?

Мне нужно написать unit test для метода, который берет поток, который поступает из текстового файла. Я хотел бы сделать что-то вроде этого:

Stream s = GenerateStreamFromString("a,b \n c,d");

Ответ 1

public static Stream GenerateStreamFromString(string s)
{
    var stream = new MemoryStream();
    var writer = new StreamWriter(stream);
    writer.Write(s);
    writer.Flush();
    stream.Position = 0;
    return stream;
}

Не забудьте использовать Использование:

using (var stream = GenerateStreamFromString("a,b \n c,d"))
{
    // ... Do stuff to stream
}

О StreamWriter не используется. StreamWriter - это всего лишь оболочка вокруг базового потока и не использует никаких ресурсов, которые необходимо утилизировать. Метод Dispose закрывает базовый Stream который пишет StreamWriter. В этом случае мы хотим вернуть MemoryStream.

В.NET 4.5 теперь есть перегрузка для StreamWriter которая поддерживает открытый поток после того, как автор удален, но этот код делает то же самое и работает с другими версиями.NET.

См. Есть ли способ закрыть StreamWriter без закрытия BaseStream?

Ответ 2

Другое решение:

public static MemoryStream GenerateStreamFromString(string value)
{
    return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
}

Ответ 3

Добавьте это в статический класс классов:

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;
}

Это добавляет функцию расширения, поэтому вы можете просто:

using (var stringStream = "My string".ToStream())
{
    // use stringStream
}

Ответ 4

public Stream GenerateStreamFromString(string s)
{
    return new MemoryStream(Encoding.UTF8.GetBytes(s));
}

Ответ 5

Используйте класс MemoryStream, вызывая Encoding.GetBytes, чтобы сначала преобразовать вашу строку в массив байтов.

Вам понадобится TextReader в потоке? Если это так, вы можете напрямую передать StringReader и обходить шаги MemoryStream и Encoding.

Ответ 6

Я использовал сочетание ответов вроде этого:

public static Stream ToStream(this string str, Encoding enc = null)
{
    enc = enc ?? Encoding.UTF8;
    return new MemoryStream(enc.GetBytes(str ?? ""));
}

И затем я использую его следующим образом:

String someStr="This is a Test";
Encoding enc = getEncodingFromSomeWhere();
using (Stream stream = someStr.ToStream(enc))
{
    // Do something with the stream....
}

Ответ 7

Здесь вы идете:

private Stream GenerateStreamFromString(String p)
{
    Byte[] bytes = UTF8Encoding.GetBytes(p);
    MemoryStream strm = new MemoryStream();
    strm.Write(bytes, 0, bytes.Length);
    return strm;
}

Ответ 8

Мы используем методы расширения, перечисленные ниже. Я думаю, вы должны заставить разработчика принять решение о кодировании, поэтому есть меньше магии.

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 ?? ""));
    }
}

Ответ 9

Я думаю, вы можете воспользоваться MemoryStream. Вы можете заполнить его строковыми байтами, которые вы получите, используя метод GetBytes Класс кодирования.

Ответ 10

Модернизированная и слегка модифицированная версия методов расширения для 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));

Модификация, предложенная в комментарии @Palec к ответу @Shaun Bowe.

Ответ 11

Если вам нужно изменить кодировку, я голосую за решение @ShaunBowe. Но каждый ответ здесь копирует всю строку в памяти хотя бы один раз. Ответы с комбо ToCharArray + BlockCopy делают это дважды.

Если это имеет значение, то это простая обертка Stream для необработанной строки UTF-16. Если используется с StreamReader выберите Encoding.Unicode для него:

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; // ;)     
}

А вот более полное решение с необходимыми проверками привязки (получено из MemoryStream поэтому оно также имеет ToArray и WriteTo).

Ответ 12

/// <summary>
/// Get Byte[] from String
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static byte[] GetBytes(string str)
{
  byte[] bytes = new byte[str.Length * sizeof(char)];
  System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
  return bytes;
}

/// <summary>
/// Get Stream from String
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static Stream GetStream(string str)
{
  return new MemoryStream(GetBytes(str));
}

Ответ 13

Хорошая комбинация расширений строк:

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;
}