2010-01-26 2 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))) 

문자열 "내용"에는 전체 스트림에 대한 올바른 문자열이 들어 있습니다.

그러나, 나는 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

인용, StreamReader.ReadToEnd 쇼의 설명을 자세히 상대 :

스트림 내에서 초기 위치를 알 수 없거나 스트림 가 추구를 지원하지 않는 경우, 기본 스트림 객체는 을 할 필요가 재 초기화.

이 더 말을, 계속 :

는 이러한 상황을 방지하고 읽기 방법을 사용하여 미리 할당 된 버퍼에서 읽기 문자를 를 저장해야 강력한 코드를 생성하기 위해.

그러나, 후드보고 만 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를 사용하여/to/end를 읽을 수 있고 올바른 출력을 얻을 수 있는지 확인했습니다. 아마도 문제를 찾는 것으로 구현하는 경우 문제가 사라질 수 있습니다. 나는 "ReadToEnd"에 대한 설명을 놓쳤다. 문제가 해결되면 문제가 해결됩니다. ReadToEnd의 BinaryReader 구현이 질문에 표시됩니다. –

+0

문제는 내 읽기 방법에있었습니다./current/read가 스트림의 끝에 도달하면 내 read 메소드는 0을 리턴합니다. 빈 스트림을 읽는 경우에만 0을 반환합니다. –

+0

아니요, 찾는 중 또는하지 않는 것이 문제가되지 않습니다. 알아 낸 것처럼 인터페이스 구현이 정확해야합니다. 모든 관련 코드를 보지 않고 이러한 오류를 찾는 것을 돕기는 어렵습니다 ...;) – Abel

0

이 일을보십시오 :

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

또한 NotImplementedException가 발생합니다 사용하지 않도록 모든 방법을 확인하십시오.

+0

그들은 System.IO.Stream 경고와 같은 NotSupportedExceptions를 발생시킵니다. NotImplementedException 대신 NotSupportedException을 의미하지 않는다고 확신합니까? –

+0

@ 에반 - 사실 상관 없습니다. 필자가 권장하는 이유는 스트림 리더가 이러한 메서드를 호출하여 어떤 일이 발생할 것으로 예상하면 throw하여 디버깅을 쉽게하기 때문입니다. – ChaosPandion

관련 문제