2011-01-20 2 views
0

들어오는 스트림은 고정 된 1024 바이트 버퍼로 제공됩니다. 스트림 자체는 포옹 XML 파일로 끝내려면 몇 차례의 읽기가 필요할 수 있습니다. 필자의 목표는 버퍼를 읽고 큰 XML 파일에서 요소가 몇 번 발생했는지 파악하는 것입니다.고정 길이 버퍼에서 읽을 XmlReader

내 chanllenge는 고정 길이 버퍼이므로 XML의 Wellform을 보장 할 수 없으므로 XmlTextReader에서 스트림을 래핑하면 항상 예외가 발생하여 읽기를 완료 할 수 없습니다. 예를 들어 요소는 abcdef 일 수 있지만 첫 번째 버퍼는 abc로 끝날 수 있지만 두 번째 버퍼는 def로 시작될 수 있습니다. 나는 이것에 관해 정말로 좌절하고있다, 누군가 스트리밍 패션을 사용하여 이것을 달성하는 더 좋은 방법을 조언 할 수 있었느냐? 어떤이 일반적으로 더 "요소를 계산하지만 메모리에 전체 XML을로드"처럼 ... 종류의 이상한 목표

+0

XmlTextReader가 솔루션이어야합니다. 버퍼를 수동으로 처리하는 대신 관리하도록합니다. – porges

답변

0

너무 많은

감사합니다 (I 메모리에 전체 내용을로드하고 싶지 않은) 사소한 - 당신이 순방향 전용 스트림 (NetworkStream과 유사)으로 버퍼를 나타내는 스트림 파생 클래스를 작성하고 XmlReader를 사용하여 XML (보통 LINQ 사용)을 읽지 만 XmlDocument는 생성하지 않습니다.

목표를 분명히하면 다른 사람들이 조언하기가 더 쉬울 수 있습니다.

+0

답장을 보내 주신 Alex 께 감사드립니다. 시나리오는 BizTalk의 파이프 라인 구성 요소의 이벤트 처리기에 코드를 작성하는 것입니다. 런타임에 BizTalk 엔진은 다운 스트림 데이터 (xml 형식)를 읽은 다음 이벤트를 발생시키고 이벤트 처리기에 고정 길이의 버퍼를 제공합니다. 내 목표는이 버퍼를 어떻게 든 소비하는 특정 요소를 소모하는 것입니다. 그러나 이것의 도전은 부분적으로 비 웰폼 된 xml이 그 안에있을 수 있기 때문에 버퍼 안에 무엇이 있는지 보장하지 못한다는 것입니다. – NINIThePug

+0

하지만 전체 문서를 메모리에 버퍼링하는 것이 옵션 인 경우 문서 처리 작업은 간단하게 –

+0

으로 단순화됩니다.이 작업은 옵션이 아닙니다. 메시지 당 백 메가 바이트를 버퍼링하는 것은 하드웨어에 범죄를 저지르고 있다고 생각합니다. – NINIThePug

1

1024 바이트 버퍼가 System.IO.Stream의 표준 구현 중 하나에서 제공되고 있습니까? t가 있다면, 당신은 단지 기본 스트림의 주위에 당신의 XmlTextReader는을 만들 수 있습니다

XmlTextReader tr = XmlTextReader.Create(myStreamInstance) ; 

그렇지 않은 경우 - 말하자면, 예를 들어, 당신은 API의 일종에서 버퍼를 "읽기"하고 - 당신이 필요 다음으로 위의 XmlReader를 인스턴스를

public class MyStream : System.IO.Stream 
{ 
    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 { throw new NotImplementedException(); } } 
    public override long Position { 
            get { throw new NotImplementedException(); } 
            set { throw new NotImplementedException(); } 
            } 

    public override int Read(byte[] buffer , int offset , int count) 
    { 
     int bytesRead = 0 ; 

     if (!initialized) 
     { 
      Initialize() ; 
     } 

     for (int bytesRemaining = count ; !atEOF && bytesRemaining > 0 ;) 
     { 

      int frameRemaining = frameLength - frameOffset ; 
      int chunkSize  = (bytesRemaining > frameRemaining ? frameRemaining : bytesRemaining) ; 

      Array.Copy(frame , offset , frame , frameOffset , chunkSize) ; 

      bytesRemaining -= chunkSize ; 
      offset   += chunkSize ; 
      bytesRead  += chunkSize ; 

      // read next frame if necessary 
      if (frameOffset >= frameLength) 
      { 
       ReadNextFrame() ; 
      } 

     } 

     return bytesRead ; 
    } 

    public override long Seek(long offset , System.IO.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(); } 
    public override void Flush()           { throw new NotImplementedException(); } 

    private byte[] frame  = null ; 
    private int frameLength = 0  ; 
    private int frameOffset = 0  ; 
    private bool atEOF  = false ; 
    private bool initialized = false ; 

    private void Initialize() 
    { 
     if (initialized) throw new InvalidOperationException() ; 

     frame  = new byte[1024] ; 
     frameLength = 0 ; 
     frameOffset = 0 ; 
     atEOF  = false ; 
     initialized = true ; 

     ReadNextFrame() ; 

     return ; 
    } 

    private void ReadNextFrame() 
    { 

     //TODO: read the next (or first 1024-byte buffer 
     //TODO: set the frame length to the number of bytes actually returned (might be less than 1024 on the last read, right? 
     //TODO: set the frame offset to 0 
     //TODO: set the atEOF flag if we've exhausted the data source ; 

     return ; 

    } 

} 

:이 라인 (당신이 할 필요가해야 모두가 ReadNextFrame 구체화() 메소드이며, 아마도 당신의 생성자를 구현)을 따라 뭔가를 자신의 구체적인 스트림을 구현

System.IO.Stream  s = new MyStream() ; 
System.Xml.XmlReader xr = XmlTextReader.Create(s) ; 

건배!

관련 문제