从Memory<byte>
对象获取TextReader
实例的最佳方式是什么?
我可以写这样的东西:
using (var stream = new MemoryStream(body.ToArray()))
using (var reader = new StreamReader(stream))
{
}
但也许还有更好的办法?
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, segment.Offset, segment.Count));
// 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!