1

我正在为我的应用程序中的 API 端点创建自定义流。流需要具有我不想进入的自定义逻辑,但足以说明我不能使用内置流类。

我做了最低限度的实现只读流(从 System.IO.Stream 继承),并且我已经验证 System.IO.BinaryReader 类可以从我的流中读取:

Dim reader As New System.IO.BinaryReader(GenerateStream(business, logic))
Dim enc As New System.Text.ASCIIEncoding
Dim contents As String = enc.GetString(reader.ReadBytes(CType(reader.BaseStream.Length, Int32)))

字符串“contents”包含整个流的正确字符串。

但是,我希望能够允许使用 System.IO.StreamReader 类:

Dim reader As New System.IO.StreamReader(GenerateStream(business, logic), System.Text.Encoding.ASCII)
Dim contents As String = reader.ReadToEnd

但无论出于何种原因,ReadToEnd 总是返回空字符串。

有任何想法吗?

这是流:

Public Overrides ReadOnly Property CanRead() As Boolean
   Get
    Return True
   End Get
  End Property

  Public Overrides ReadOnly Property CanSeek() As Boolean
   Get
    Return False
   End Get
  End Property

  Public Overrides ReadOnly Property CanWrite() As Boolean
   Get
    Return False
   End Get
  End Property

  Public Overrides Sub Flush()
   'this method intentionally left blank'
  End Sub

  Public Overrides ReadOnly Property Length() As Long
   Get
    Return 'some business logic'
   End Get
  End Property

  Public Overrides Property Position() As Long
   Get
    Return bytePosition
   End Get
   Set(ByVal value As Long)
    Throw New System.NotSupportedException
   End Set
  End Property

  Public Overrides Function Read(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer) As Integer
   'I return 0 on an end of stream, otherwise the # of bytes successfully read.'
  End Function

  Public Overrides Function Seek(ByVal offset As Long, ByVal origin As System.IO.SeekOrigin) As Long
   Throw New System.NotSupportedException
  End Function

  Public Overrides Sub SetLength(ByVal value As Long)
   Throw New System.NotSupportedException()
  End Sub

  Public Overrides Sub Write(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer)
   Throw New System.NotSupportedException()
  End Sub
4

2 回答 2

2

仔细查看节目的描述StreamReader.ReadToEnd,引用:

如果流中的初始位置未知或流不支持查找,则还需要重新初始化底层 Stream 对象。

它进一步说:

为了避免这种情况并生成健壮的代码,您应该使用 Read 方法并将读取的字符存储在预分配的缓冲区中。

但是,从底层看,似乎只有 Stream.Read 被调用,它应该提供你需要的输出。但是,您确实知道 StreamReader 读取字符,它会努力将数据解释为字符串。如果不能,不确定会发生什么。数据由什么组成?


更新:考虑以下测试代码(对不起,C#,但使用转换器来获取您的代码),我没有包含抽象类中的未实现方法,以免分散核心的注意力。作为概念证明,这似乎适用于 ASCII 编码,无需重新初始化或实现 Seek。

public class AsciiStream : Stream
{
    private string dataStream = "abcdefghijklmnopqrstuvwxyz";
    private long position = 0;

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }

    public override bool CanWrite
    {
        get { return false; }
    }


    public override long Length
    {
        get { return dataStream.Length; }
    }

    public override long Position
    {
        get
        {
            return position;
        }
        set
        {
            position = value < this.Length ? value : this.Length;
        }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        long bufferPos = offset;
        long max = this.position + count;
        max = max < this.Length ? max : this.Length;
        for (; this.position < max; this.position++)
        {
            buffer[bufferPos] = Convert.ToByte(this.dataStream[(int) this.position]);
            bufferPos++;
        }

        return (int) bufferPos - offset;
    }
}


// call the code like as follows:
StreamReader sReader = new StreamReader(new AsciiStream(), Encoding.ASCII);
string sToEnd = sReader.ReadToEnd();

要点是:问题必须出在您的实际读取代码或您未向我们展示的业务逻辑中。您选择的方法本身应该很有效。您是否尝试过手动实现“从头到尾”?还是用BinaryReaderReadBytes(many)`` 读到末尾?

于 2010-01-26T01:00:35.287 回答
0

尝试这样做:

Dim reader As New System.IO.StreamReader(
    GenerateStream(business, logic), 
    System.Text.Encoding.ASCII, 
    False
)
Dim contents As String = reader.ReadToEnd

还要确保您不想使用的所有方法都会抛出NotImplementedException.

于 2010-01-26T00:52:04.597 回答