C# 内存到 TextReader
C# Memory to TextReader
从 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
但是在这里您将整个内存内容复制到另一个数组中,它是 memory-consuming 并且给垃圾收集器更多的工作。不推荐,尤其是当数组包含大量数据时。
还有另一种不分配新数组的方法。
#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
returns源内存区域为数组
测试
这是一个使用它的示例(基于 .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!
从 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
但是在这里您将整个内存内容复制到另一个数组中,它是 memory-consuming 并且给垃圾收集器更多的工作。不推荐,尤其是当数组包含大量数据时。
还有另一种不分配新数组的方法。
#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
returns源内存区域为数组
测试
这是一个使用它的示例(基于 .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!