StreamReader
автоматически удалит базовый Stream
.
# 1 Самый простой способ
Memory<byte> memory = GetSomeData();
using TextReader reader = new StreamReader(new MemoryStream(memory.ToArray()));
// some code
Но здесь вы копируете все содержимое памяти в другой массив, это потребляет много памяти и дает сборщику мусора больше работы. Не рекомендуется, особенно если массив содержит большой объем данных.
Есть другой способ сделать это без выделения нового массива.
# 2 Оптимальный способ (рекомендуется для экономии памяти)
Memory<byte> memory = GetSomeData();
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment))
{
using TextReader reader = new StreamReader(new MemoryStream(segment.Array));
// some code
}
Другими словами, ArraySegment
возвращает исходную область памяти в виде массива.
Тесты
Вот пример для игры (на основе консольного приложения .NET Core 3.1).
class Program
{
static void Main(string[] args)
{
string text = "Hello World!";
byte[] data = Encoding.UTF8.GetBytes(text);
Memory<byte> memory = data;
byte[] data1 = memory.ToArray();
Console.WriteLine("data == data1: {0}", data == data1);
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment))
{
byte[] data2 = segment.Array;
Console.WriteLine("data == data2: {0}", data == data2);
}
Console.WriteLine();
Console.WriteLine("Test 1");
Test1(text);
Console.WriteLine();
Console.WriteLine("Test 2");
Test2(text);
Console.ReadKey();
}
private static void Test1(string text)
{
Memory<byte> memory = Encoding.UTF8.GetBytes(text);
byte[] data = memory.ToArray();
ReadItTwice(memory, data);
}
private static void Test2(string text)
{
Memory<byte> memory = Encoding.UTF8.GetBytes(text);
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment))
{
byte[] data = segment.Array;
ReadItTwice(memory, data);
}
}
private static void ReadItTwice(Memory<byte> memory, byte[] data)
{
using MemoryStream ms = new MemoryStream(data);
using TextReader sr = new StreamReader(ms);
Console.WriteLine("Before change: {0}", sr.ReadToEnd());
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment))
segment.Array[0] = (byte)'_'; // change first symbol
ms.Position = 0;
Console.WriteLine("After change: {0}", sr.ReadToEnd());
}
}
Выход
data == data1: False
data == data2: True
Test 1
Before change: Hello World!
After change: Hello World!
Test 2
Before change: Hello World!
After change: _ello World!
person
aepot
schedule
12.08.2020