一个例子(可能不是现实生活,但要说明我的观点):
public void StreamInfo(StreamReader p)
{
string info = string.Format(
"The supplied streamreaer read : {0}\n at line {1}",
p.ReadLine(),
p.GetLinePosition()-1);
}
Run Code Online (Sandbox Code Playgroud)
GetLinePosition这是streamreader的虚构扩展方法.这可能吗?
当然,我可以自己计算,但这不是问题.
Eam*_*mon 21
我在寻找类似问题的解决方案的同时,我需要寻找StreamReader到特定的行.我最终创建了两个扩展方法来获取和设置StreamReader上的位置.它实际上并没有提供行号计数,但实际上,我只是抓住每个ReadLine()之前的位置,如果该行感兴趣,那么我保留起始位置以便稍后设置回到这样的行:
var index = streamReader.GetPosition();
var line1 = streamReader.ReadLine();
streamReader.SetPosition(index);
var line2 = streamReader.ReadLine();
Assert.AreEqual(line1, line2);
Run Code Online (Sandbox Code Playgroud)
而重要的部分:
public static class StreamReaderExtensions
{
readonly static FieldInfo charPosField = typeof(StreamReader).GetField("charPos", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | BindingFlags.DeclaredOnly);
readonly static FieldInfo byteLenField = typeof(StreamReader).GetField("byteLen", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | BindingFlags.DeclaredOnly);
readonly static FieldInfo charBufferField = typeof(StreamReader).GetField("charBuffer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | BindingFlags.DeclaredOnly);
public static long GetPosition(this StreamReader reader)
{
//shift position back from BaseStream.Position by the number of bytes read
//into internal buffer.
int byteLen = (int)byteLenField.GetValue(reader);
var position = reader.BaseStream.Position - byteLen;
//if we have consumed chars from the buffer we need to calculate how many
//bytes they represent in the current encoding and add that to the position.
int charPos = (int)charPosField.GetValue(reader);
if (charPos > 0)
{
var charBuffer = (char[])charBufferField.GetValue(reader);
var encoding = reader.CurrentEncoding;
var bytesConsumed = encoding.GetBytes(charBuffer, 0, charPos).Length;
position += bytesConsumed;
}
return position;
}
public static void SetPosition(this StreamReader reader, long position)
{
reader.DiscardBufferedData();
reader.BaseStream.Seek(position, SeekOrigin.Begin);
}
}
Run Code Online (Sandbox Code Playgroud)
这对我来说效果很好,取决于你使用反射的容忍度它认为这是一个相当简单的解决方案.
注意事项:
Ada*_*son 11
不,不太可能."行号"的概念基于已经读取的实际数据,而不仅仅是位置.例如,如果您要将读者Seek()移到任意位置,那么它不会实际读取该数据,因此无法确定行号.
唯一的方法是自己跟踪它.
小智 7
为任何TextReader提供行计数包装非常容易:
public class PositioningReader : TextReader {
private TextReader _inner;
public PositioningReader(TextReader inner) {
_inner = inner;
}
public override void Close() {
_inner.Close();
}
public override int Peek() {
return _inner.Peek();
}
public override int Read() {
var c = _inner.Read();
if (c >= 0)
AdvancePosition((Char)c);
return c;
}
private int _linePos = 0;
public int LinePos { get { return _linePos; } }
private int _charPos = 0;
public int CharPos { get { return _charPos; } }
private int _matched = 0;
private void AdvancePosition(Char c) {
if (Environment.NewLine[_matched] == c) {
_matched++;
if (_matched == Environment.NewLine.Length) {
_linePos++;
_charPos = 0;
_matched = 0;
}
}
else {
_matched = 0;
_charPos++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
缺点(为简洁起见):
public override int ReadBlock(char[] buffer, int index, int count) {
var readCount = _inner.ReadBlock(buffer, index, count);
for (int i = 0; i < readCount; i++)
AdvancePosition(buffer[index + i]);
return readCount;
}
Run Code Online (Sandbox Code Playgroud)
没有.
考虑到可以使用底层流对象(可以在任何行中的任何点)寻找任何poisition.现在考虑一下StreamReader保留的任何计数会做什么.
StreamReader应该去找出它现在在哪条线上吗?它是否应该只读取多行,而不管文件中的位置如何?
imho,还有更多的问题不仅仅是让这成为一个噩梦.
| 归档时间: |
|
| 查看次数: |
26449 次 |
| 最近记录: |