在C#中如何将字符串转换为ReadOnlyMemory<byte>?

5
我想将一个字符串转换为只读内存对象。将字符串转换为只读内存对象很容易(使用.AsMemory()),但没有直接的方法将其转换为字节类型,也没有直接将字符串转换的方法。

1
因为你正在使用需要 ReadOnlyMemory<byte> 数组的 API,而且没有直接的转换方式,这就是我发布了我所做的回答的原因吗? - Tom Warner
1
我已经发布了类的链接。答案比我在评论中写的要多一点。再次问,你打算如何使用那个Memory<>?这很重要。最好直接写入PipeWriter,而不是创建一个中间缓冲区。Memory<>Span<>和管道的整个目的是通过缓冲区重用来提高内存效率。 - Panagiotis Kanavos
1
内存效率并不是一个无聊的问题。通过避免内存分配和垃圾回收,它至少可以带来10-100倍的更好性能。当垃圾回收发生时,GC会变得昂贵并拖慢应用程序。ASP.NET Core之所以如此快,正是因为它试图避免浪费内存。 - Panagiotis Kanavos
1
@TomWarner,你没有理解重点。重点是你的代码不应该创建和复制新的byte[]缓冲区。应该是你的代码应该重用缓冲区。那个API是否有一个接受PipeReader而不是ReadOnlyMemory<>的方法?那将更加高效。 - Panagiotis Kanavos
那么你的回答的吸引力在于它不使用额外的缓冲区来复制数据?而且该API不接受PipeReader。我真的不明白为什么它需要一个ReadOnlyMemory<byte>,因为据我所知它应该只接受一个字符串,但是我们现在就是这样。 - Tom Warner
显示剩余7条评论
2个回答

2
有一种方法。EncodingExtensions类包含GetBytes扩展方法,可以写入IBuffeWriter< T>。两个内置类实现了这个接口,ArrayBufferWriter<>PipeWriter
在使用 System.IO.Pipelines 的 API 中,直接写入 PipeWriter 要比创建中间对象更好。我将使用 ArrayBufferWriter,因为它更容易。它仍然允许重复使用内存而不是分配新的缓冲区:
var text=".....";
var writer=new ArrayBufferWrite(8192);

Encoding.UTF8.GetBytes(text,writer);

var memory=writer.WrittenMemory;

WrittenMemory 返回一个包含写入数据的 ReadOnlyMemory<T> 对象。

可以使用 Reset() 清空缓冲区并重用:

var writer=new ArrayBufferWrite(8192);
while(true)
{
    writer.Reset();
    var text=SomehowGetString();
    
    Encoding.UTF8.GetBytes(text,writer);

    var memory=writer.WrittenMemory;
    ...
}

1
我发现最直接的方法是将字符串转换为byte[],然后将其作为ReadOnlyMemory返回,如下所示:
var memory = new ReadOnlyMemory<byte>(Encoding.UTF8.GetBytes(str));

2
不完全是这样。首先,.NET字符串是UTF16编码的。虽然不会丢失任何信息,但仍然需要进行转换。更重要的是,Encoding.GetBytes()会创建一个新的缓冲区,那么使用ReadOnlyMemory有什么意义呢? - Panagiotis Kanavos
2
最好使用其中一个写入到IBufferWriterGetBytes扩展方法,例如ArrayBufferWritter或PipelineWriter。这样可以在调用之间重复使用缓冲区。您可以使用WrittenMemorry来获取字节。 - Panagiotis Kanavos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接