Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading a line from a streamreader without consuming?

Is there a way to read ahead one line to test if the next line contains specific tag data?

I'm dealing with a format that has a start tag but no end tag.

I would like to read a line add it to a structure then test the line below to make sure it not a new "node" and if it isn't keep adding if it is close off that struct and make a new one

the only solution i can think of is to have two stream readers going at the same time kinda suffling there way along lock step but that seems wastefull (if it will even work)

i need something like peek but peekline

like image 436
Crash893 Avatar asked May 09 '09 01:05

Crash893


People also ask

How do I use StreamReader?

Open(FileMode. OpenOrCreate, FileAccess. Read , FileShare. Read); //Create an object of StreamReader by passing FileStream object on which it needs to operates on StreamReader sr = new StreamReader(fs); //Use the ReadToEnd method to read all the content from file string fileContent = sr.

What is StreamReader and StreamWriter?

The StreamReader and StreamWriter classes are used for reading from and writing data to text files. These classes inherit from the abstract base class Stream, which supports reading and writing bytes into a file stream.

How read a string from line by line in C #?

fgets() process input from a FILE pointer. You can implement it yourself, a simple looping until new line or NULL is seen, keeping on a variable with static storage class the offset where loop stoped and in next functions call you start from this offset.

How does StreamReader work in C#?

C# StreamReader is used to read characters to a stream in a specified encoding. StreamReader. Read method reads the next character or next set of characters from the input stream. StreamReader is inherited from TextReader that provides methods to read a character, block, line, or all content.


2 Answers

The problem is the underlying stream may not even be seekable. If you take a look at the stream reader implementation it uses a buffer so it can implement TextReader.Peek() even if the stream is not seekable.

You could write a simple adapter that reads the next line and buffers it internally, something like this:

 public class PeekableStreamReaderAdapter     {         private StreamReader Underlying;         private Queue<string> BufferedLines;          public PeekableStreamReaderAdapter(StreamReader underlying)         {             Underlying = underlying;             BufferedLines = new Queue<string>();         }          public string PeekLine()         {             string line = Underlying.ReadLine();             if (line == null)                 return null;             BufferedLines.Enqueue(line);             return line;         }           public string ReadLine()         {             if (BufferedLines.Count > 0)                 return BufferedLines.Dequeue();             return Underlying.ReadLine();         }     } 
like image 135
Nic Strong Avatar answered Sep 20 '22 05:09

Nic Strong


You could store the position accessing StreamReader.BaseStream.Position, then read the line next line, do your test, then seek to the position before you read the line:

            // Peek at the next line             long peekPos = reader.BaseStream.Position;             string line = reader.ReadLine();              if (line.StartsWith("<tag start>"))             {                 // This is a new tag, so we reset the position                 reader.BaseStream.Seek(pos);                  }             else             {                 // This is part of the same node.             } 

This is a lot of seeking and re-reading the same lines. Using some logic, you may be able to avoid this altogether - for instance, when you see a new tag start, close out the existing structure and start a new one - here's a basic algorithm:

        SomeStructure myStructure = null;         while (!reader.EndOfStream)         {             string currentLine = reader.ReadLine();             if (currentLine.StartsWith("<tag start>"))             {                 // Close out existing structure.                 if (myStructure != null)                 {                     // Close out the existing structure.                 }                  // Create a new structure and add this line.                 myStructure = new Structure();                                    // Append to myStructure.             }             else             {                 // Add to the existing structure.                 if (myStructure != null)                 {                     // Append to existing myStructure                 }                 else                 {                     // This means the first line was not part of a structure.                     // Either handle this case, or throw an exception.                 }             }         } 
like image 33
seddy Avatar answered Sep 23 '22 05:09

seddy