在不复制的情况下将字符串作为流读取 [英] Reading string as a stream without copying

查看:87
本文介绍了在不复制的情况下将字符串作为流读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在字符串中有一些数据.我有一个将流作为输入的函数.我想将数据提供给函数,而不必将完整的字符串复制到流中.本质上,我正在寻找可以包装字符串并从中读取的流类.

I have some data in a string. I have a function that takes a stream as input. I want to provide my data to my function without having to copy the complete string into a stream. Essentially I'm looking for a stream class that can wrap a string and read from it.

我在网上看到的唯一建议是不是一个流的StringReader,或者创建一个内存流并对其进行写入,这意味着复制数据.我可以编写自己的流对象,但棘手的部分是处理编码,因为流以字节为单位.有没有一种方法而无需编写新的流类?

The only suggestions I've seen online suggest the StringReader which is NOT a stream, or creating a memory stream and writing to it, which means copying the data. I could write my own stream object but the tricky part is handling encoding because a stream deals in bytes. Is there a way to do this without writing new stream classes?

我正在BizTalk中实现管道组件. BizTalk完全通过流处理所有内容,因此您总是将内容通过流传递给BizTalk. BizTalk将始终以小块的形式从该流中读取,因此,如果我可以从流中读取BizTalk的需求,则将整个字符串复制到流中(特别是如果字符串很大的话)是没有意义的.

I'm implementing pipeline components in BizTalk. BizTalk deals with everything entirely with streams, so you always pass things to BizTalk in a stream. BizTalk will always read from that stream in small chunks, so it doesn't make sense to copy the entire string to a stream (especially if the string is large), if I can read from the stream how BizTalk wants it.

推荐答案

这是一个适当的StringReaderStream,具有以下缺点:

Here is a proper StringReaderStream with following drawbacks:

  • Read的缓冲区长度必须至少为maxBytesPerChar.通过保留内部一个char buff = new byte[maxBytesPerChar],可以为小型缓冲区实现Read.但是对于大多数用法而言,并不是必须的.
  • Seek,可以进行搜索,但一般来说会非常棘手. (有些寻求案例,例如寻求开始,寻求结束,很容易实现.)
  • The buffer for Read has to be at least maxBytesPerChar long. It's possible to implement Read for small buffers by keeping internal one char buff = new byte[maxBytesPerChar]. But's not necessary for most usages.
  • No Seek, it's possible to do seek, but would be very tricky generaly. (Some seek cases, like seek to beginning, seek to end, are simple to implement. )
/// <summary>
/// Convert string to byte stream.
/// <para>
/// Slower than <see cref="Encoding.GetBytes()"/>, but saves memory for a large string.
/// </para>
/// </summary>
public class StringReaderStream : Stream
{
    private string input;
    private readonly Encoding encoding;
    private int maxBytesPerChar;
    private int inputLength;
    private int inputPosition;
    private readonly long length;
    private long position;

    public StringReaderStream(string input)
        : this(input, Encoding.UTF8)
    { }

    public StringReaderStream(string input, Encoding encoding)
    {
        this.encoding = encoding ?? throw new ArgumentNullException(nameof(encoding));
        this.input = input;
        inputLength = input == null ? 0 : input.Length;
        if (!string.IsNullOrEmpty(input))
            length = encoding.GetByteCount(input);
            maxBytesPerChar = encoding == Encoding.ASCII ? 1 : encoding.GetMaxByteCount(1);
    }

    public override bool CanRead => true;

    public override bool CanSeek => false;

    public override bool CanWrite => false;

    public override long Length => length;

    public override long Position
    {
        get => position;
        set => throw new NotImplementedException();
    }

    public override void Flush()
    {
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (inputPosition >= inputLength)
            return 0;
        if (count < maxBytesPerChar)
            throw new ArgumentException("count has to be greater or equal to max encoding byte count per char");
        int charCount = Math.Min(inputLength - inputPosition, count / maxBytesPerChar);
        int byteCount = encoding.GetBytes(input, inputPosition, charCount, buffer, offset);
        inputPosition += charCount;
        position += byteCount;
        return byteCount;
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotImplementedException();
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }
}

这篇关于在不复制的情况下将字符串作为流读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆