Skip to content

Instantly share code, notes, and snippets.

@andyedinborough
Created October 26, 2011 18:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andyedinborough/1317325 to your computer and use it in GitHub Desktop.
Save andyedinborough/1317325 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
namespace AE.Net.Mail {
//http://stackoverflow.com/questions/842465/reading-a-line-from-a-streamreader-without-consuming
public class PeekableTextReader : TextReader {
private TextReader _Underlying;
private MemoryStream _Buffer;
private StreamReader _BufferReader;
private StreamWriter _BufferWriter;
private long _BufferPosition = 0;
public PeekableTextReader(TextReader underlying) {
_Underlying = underlying;
_Buffer = new System.IO.MemoryStream();
_BufferReader = new StreamReader(_Buffer);
_BufferWriter = new StreamWriter(_Buffer);
}
public string PeekLine() {
string line = _Underlying.ReadLine();
if (line == null) return null;
_Buffer.Seek(0, SeekOrigin.End);
_BufferWriter.WriteLine(line);
_BufferWriter.Flush();
_Buffer.Seek(_BufferPosition, SeekOrigin.Begin);
return line;
}
public override int Peek() {
var read = _Underlying.Read();
_Buffer.Seek(0, SeekOrigin.End);
_BufferWriter.Write(read);
_BufferWriter.Flush();
_Buffer.Seek(_BufferPosition, SeekOrigin.Begin);
return read;
}
public override void Close() {
_Underlying.Close();
}
public override System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType) {
return _Underlying.CreateObjRef(requestedType);
}
protected override void Dispose(bool disposing) {
if (disposing) {
TryDispose(ref _Underlying);
TryDispose(ref _Buffer);
TryDispose(ref _BufferReader);
TryDispose(ref _BufferWriter);
}
}
private void TryDispose<T>(ref T obj) where T : class, IDisposable {
try {
if (obj != null) {
obj.Dispose();
}
} catch (Exception) { }
obj = null;
}
public override bool Equals(object obj) {
return _Underlying.Equals(obj);
}
public override int GetHashCode() {
return _Underlying.GetHashCode();
}
public override object InitializeLifetimeService() {
return _Underlying.InitializeLifetimeService();
}
public override string ReadLine() {
if (_Buffer.Length > _BufferPosition) {
var line = ReadFromBuffer(rdr => rdr.ReadLine());
return line;
} else {
return _Underlying.ReadLine();
}
}
public override int Read() {
if (_Buffer.Length > _BufferPosition) {
return ReadFromBuffer(rdr => rdr.Read());
} else {
return _Underlying.Read();
}
}
private T ReadFromBuffer<T>(Func<StreamReader, T> cmd) {
if (_BufferPosition != _Buffer.Position) {
_Buffer.Seek(_BufferPosition, SeekOrigin.Begin);
}
var value = cmd(_BufferReader);
_BufferPosition = _Buffer.Position;
return value;
}
public override int Read(char[] buffer, int index, int count) {
if (_Buffer.Length > _BufferPosition) {
var read = ReadFromBuffer(rdr => rdr.Read(buffer, index, count));
if (count > read && _Buffer.Position == _Buffer.Length) {
read += _Underlying.Read(buffer, index + read, count - read);
}
return read;
} else {
return _Underlying.Read(buffer, index, count);
}
}
public override int ReadBlock(char[] buffer, int index, int count) {
if (_Buffer.Length > _BufferPosition) {
var read = ReadFromBuffer(rdr => rdr.ReadBlock(buffer, index, count));
if (count > read && _Buffer.Position == _Buffer.Length) {
read += _Underlying.ReadBlock(buffer, index + read, count - read);
}
return read;
} else {
return _Underlying.ReadBlock(buffer, index, count);
}
}
public override string ReadToEnd() {
if (_Buffer.Length > _BufferPosition) {
return ReadFromBuffer(rdr => rdr.ReadToEnd()) + _Underlying.ReadToEnd();
} else {
return _Underlying.ReadToEnd();
}
}
}
}
@OndraTakacs
Copy link

Not recommended, PeekLine() is bugged,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment