假设您希望自定义 StreamReader 可用于任何可以使用 TextReader 的地方,通常有两个选项。
从 StreamReader 继承并覆盖您希望以不同方式工作的函数。在您的情况下,这将是 StreamReader.ReadLine。
从 TextReader 继承并完全按照您的要求实现阅读器功能。
注意:对于上面的选项 2,您可以维护对 StreamReader 实例的内部引用,并将所有功能委托给内部实例,但要替换的功能除外。在我看来,这只是选项 2 的实现细节,而不是第 3 选项。
根据您的问题,我假设您已尝试过选项 1,并发现重写 StreamReader.ReadLine 相当困难,因为您无法访问该类的内部。对于 StreamReader,您很幸运,并且无需访问 StreamReader 的内部实现即可实现这一目标。
这是一个简单的例子:
免责声明:ReadLine() 实现仅用于演示目的,并非旨在成为健壮或完整的实现。
class CustomStreamReader : StreamReader
{
public CustomStreamReader(Stream stream)
: base(stream)
{
}
public override string ReadLine()
{
int c;
c = Read();
if (c == -1)
{
return null;
}
StringBuilder sb = new StringBuilder();
do
{
char ch = (char)c;
if (ch == ',')
{
return sb.ToString();
}
else
{
sb.Append(ch);
}
} while ((c = Read()) != -1);
return sb.ToString();
}
}
您会注意到我只是使用 StreamReader.Read() 方法从流中读取字符。虽然性能肯定不如直接使用内部缓冲区,但Read() 方法确实使用了内部缓冲,因此仍应产生相当不错的性能,但应进行测试以确认。
为了好玩,这里是选项2的例子。我使用封装的StreamReader来减少实际代码,这个根本没有测试..
class EncapsulatedReader : TextReader
{
private StreamReader _reader;
public EncapsulatedReader(Stream stream)
{
_reader = new StreamReader(stream);
}
public Stream BaseStream
{
get
{
return _reader.BaseStream;
}
}
public override string ReadLine()
{
int c;
c = Read();
if (c == -1)
{
return null;
}
StringBuilder sb = new StringBuilder();
do
{
char ch = (char)c;
if (ch == ',')
{
return sb.ToString();
}
else
{
sb.Append(ch);
}
} while ((c = Read()) != -1);
return sb.ToString();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_reader.Close();
}
base.Dispose(disposing);
}
public override int Peek()
{
return _reader.Peek();
}
public override int Read()
{
return _reader.Read();
}
public override int Read(char[] buffer, int index, int count)
{
return _reader.Read(buffer, index, count);
}
public override int ReadBlock(char[] buffer, int index, int count)
{
return _reader.ReadBlock(buffer, index, count);
}
public override string ReadToEnd()
{
return _reader.ReadToEnd();
}
public override void Close()
{
_reader.Close();
base.Close();
}
}