Ответы:
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:
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?
GenerateStreamFromStringметоде вы не используете Use with StreamWriter. Есть причина для этого?
StreamWriterв любом случае, вероятно, делает то, что вы сказали внутри. Преимущество - инкапсуляция и более простой код, но за счет абстрагирования от таких вещей, как кодирование. Это зависит от того, чего вы пытаетесь достичь.
Другое решение:
public static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.UTF8.GetBytes(value ?? ""));
}
new MemoryStream(Encoding.UTF8.GetBytes("\ufeff" + (value ?? ""))если вам нужно включить спецификацию в начале потока
new MemoryStream( value, false ), Вы не можете сделать поток доступным только для чтения, если вам нужно записать его с помощью средства записи потока.
Добавьте это в служебный класс статической строки:
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
}
StreamWriter. Исправление состояло в том, чтобы использовать другой конструктор - тот, который позволял мне указывать оставлять открытыми .
public Stream GenerateStreamFromString(string s)
{
return new MemoryStream(Encoding.UTF8.GetBytes(s));
}
Используйте MemoryStreamкласс, вызывая, Encoding.GetBytesчтобы сначала превратить вашу строку в массив байтов.
Нужно ли вам впоследствии TextReaderв потоке? Если это так, вы можете поставить StringReaderнапрямую, и обойти MemoryStreamи Encodingшаги.
Я использовал смесь ответов, как это:
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....
}
Мы используем методы расширения, перечисленные ниже. Я думаю, что вы должны сделать так, чтобы разработчик принял решение о кодировке, чтобы не было никакой магии.
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 ?? ""));
}
}
return ToStream(s, Encoding.UTF8);. В текущей реализации ( return s.ToStream(Encoding.UTF8);разработчик вынужден думать сложнее, чтобы понять код, и кажется, что случай s == nullне обрабатывается и выбрасывает NullReferenceException.
Ну вот:
private Stream GenerateStreamFromString(String p)
{
Byte[] bytes = UTF8Encoding.GetBytes(p);
MemoryStream strm = new MemoryStream();
strm.Write(bytes, 0, bytes.Length);
return strm;
}
Модернизированная и слегка модифицированная версия методов расширения для 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.
Я думаю, что вы можете извлечь выгоду из использования MemoryStream . Вы можете заполнить его строковыми байтами, полученными с помощью метода GetBytes класса Encoding .
Если вам нужно изменить кодировку, я голосую за решение @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методов).
Хорошая комбинация расширений String:
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;
}
StringReaderStreamВ stackoverflow.com/a/55170901/254109