为什么System.IO.StreamReader不能从我的自定义流中读取?

时间:2010-01-26 00:40:39

标签: .net streamreader

我正在为我的应用中的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

2 个答案:

答案 0 :(得分:2)

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

  

如果在初始位置内   流是未知的或流是   不支持寻求,潜在的   流对象也需要   重新初始化。

它继续说道:

  

避免这种情况并产生   健壮的代码你应该使用Read   方法并存储读取的字符   在预先分配的缓冲区中。

但是,在引擎盖下,只看到Stream.Read,它似乎提供您需要的输出。但是,您确实知道StreamReader读取字符,它会努力将数据解释为字符串。不确定如果不能发生会发生什么。数据由什么组成?


更新 :请考虑以下测试代码(抱歉,C#,但使用a converter来获取代码),我没有包含未实现的代码抽象类中的方法,以免分散核心。正如概念证明一样,这似乎适用于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();

重点是:问题必须在于您的实际读取代码或您未向我们展示的业务逻辑。你选择的方法本身就应该起作用。您是否尝试过手动执行“读取到结束”?或者使用BinaryReader,用ReadBytes(很多)``?

读取结尾

答案 1 :(得分:0)

尝试这样做:

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

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