2010-01-26 98 views
1

我正在为我的应用程序中的API端点创建自定义流。该流需要具有我不想进入的自定义逻辑,但足以说我不能使用内置流类。为什么System.IO.StreamReader不能从我的自定义流中读取?

我做了必要的最低限度,以实现一个只读流(从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

仔细观察,报价:

如果 流中的初始位置不明或者该流不 不支持查找,底层 Stream对象也需要 重新初始化。

它进一步推移,他说:

为了避免这种情况,生产 健壮的代码,你应该使用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(很多)?

+0

数据是字符(在这种情况下用ascii编码)。我没有试过用BinaryReader读取流的结尾,但是我已经验证了你可以用BinaryReader读/结束,并且你得到正确的输出。 虽然也许如果我实现寻求问题将会消失。尽管我确实错过了“ReadToEnd”的描述。如果寻求解决问题,这是答案。 问题中显示ReadToEnd的BinaryReader实现。 – 2010-01-26 15:43:59

+0

问题确实存在于我的阅读方法中。如果/ current/read达到流的末尾,我的读取方法将返回0。现在只有在从空流读取时才返回0。 – 2010-01-27 19:19:42

+0

不,寻求或不寻求不是问题。正如你发现的那样,你的接口实现必须是正确的。如果没有看到所有相关的代码,就很难找到这样的错误......;) – Abel 2010-01-28 02:03:43

0

试着这样做:

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

同时确保所有你不想使用将抛出NotImplementedException方法。在StreamReader.ReadToEnd展示说明

+0

他们抛出NotSupportedExceptions,像System.IO.Stream警告会发生。你确定你不是指NotSupportedException而不是NotImplementedException? – 2010-01-26 15:46:36

+0

@Evan - 这其实并不重要。我推荐这个的原因是因为如果Stream Reader调用这些方法期望发生某些事情,它会抛出并因此使您的调试变得更加容易。 – ChaosPandion 2010-01-26 15:52:37

相关问题