C# 跟踪流阅读器行的位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10189270/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Tracking the position of the line of a streamreader
提问by johnnie
Hi guys what i need to do is track the position of the line that I am reading from the stream reader when I say reader.ReadLine()i need to know the position of that line in the file and I also want to be able to then read the file from the position i have previously tracked.
嗨,伙计们,我需要做的是跟踪我从流阅读器中读取的行的位置,当我说reader.ReadLine()我需要知道该行在文件中的位置时,我也希望能够从中读取文件我之前跟踪的位置。
Is this possible? If so please assist.
这可能吗?如果是这样,请提供帮助。
Help is much appreciated
非常感谢帮助
Thanks in advance.
提前致谢。
采纳答案by Chris Gessler
You can do this one of three ways:
您可以通过以下三种方式之一执行此操作:
1) Write your own StreamReader. Here's a good place to start: How to know position(linenumber) of a streamreader in a textfile?
1) 编写您自己的 StreamReader。这是一个很好的起点:如何知道文本文件中流阅读器的位置(行号)?
2) The StreamReader class has two very important, but private variables called charPos and charLen that are needed in locating the actual "read" position and not just the underlying position of the stream. You could use reflection to get the values as suggested here
2) StreamReader 类有两个非常重要的私有变量,称为 charPos 和 charLen,它们是定位实际“读取”位置所必需的,而不仅仅是流的底层位置。您可以使用反射来获取此处建议的值
Int32 charpos = (Int32) s.GetType().InvokeMember("charPos", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField ,null, s, null); Int32 charlen= (Int32) s.GetType().InvokeMember("charLen", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField ,null, s, null); return (Int32)s.BaseStream.Position-charlen+charpos;
Int32 charpos = (Int32) s.GetType().InvokeMember("charPos", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField ,null, s, null); Int32 charlen= (Int32) s.GetType().InvokeMember("charLen", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField ,null, s, null); return (Int32)s.BaseStream.Position-charlen+charpos;
3) Simply read the entire file into a string array. Something like this:
3)只需将整个文件读入一个字符串数组。像这样的东西:
char[] CRLF = new char[2] { '\n', '\r' }; TextReader tr = File.OpenText("some path to file"); string[] fileLines = tr.ReadToEnd().Split(CRLF);
char[] CRLF = new char[2] { '\n', '\r' }; TextReader tr = File.OpenText("some path to file"); string[] fileLines = tr.ReadToEnd().Split(CRLF);
Another possibility (along the sames lines as #3) is to read in the lines and store the line in an array. When you want to read the prior line, just use the array.
另一种可能性(沿着与#3 相同的行)是读入行并将该行存储在数组中。当您想读取前一行时,只需使用数组。
回答by Fernando Diaz Toledano
Maybe this can help you
也许这可以帮助你
public class StreamLineReader : IDisposable
{
const int BufferLength = 1024;
Stream _Base;
int _Read = 0, _Index = 0;
byte[] _Bff = new byte[BufferLength];
long _CurrentPosition = 0;
int _CurrentLine = 0;
/// <summary>
/// CurrentLine number
/// </summary>
public long CurrentPosition { get { return _CurrentPosition; } }
/// <summary>
/// CurrentLine number
/// </summary>
public int CurrentLine { get { return _CurrentLine; } }
/// <summary>
/// Constructor
/// </summary>
/// <param name="stream">Stream</param>
public StreamLineReader(Stream stream) { _Base = stream; }
/// <summary>
/// Count lines and goto line number
/// </summary>
/// <param name="goToLine">Goto Line number</param>
/// <returns>Return true if goTo sucessfully</returns>
public bool GoToLine(int goToLine) { return IGetCount(goToLine, true) == goToLine; }
/// <summary>
/// Count lines and goto line number
/// </summary>
/// <param name="goToLine">Goto Line number</param>
/// <returns>Return the Count of lines</returns>
public int GetCount(int goToLine) { return IGetCount(goToLine, false); }
/// <summary>
/// Internal method for goto&Count
/// </summary>
/// <param name="goToLine">Goto Line number</param>
/// <param name="stopWhenLine">Stop when found the selected line number</param>
/// <returns>Return the Count of lines</returns>
int IGetCount(int goToLine, bool stopWhenLine)
{
_Base.Seek(0, SeekOrigin.Begin);
_CurrentPosition = 0;
_CurrentLine = 0;
_Index = 0;
_Read = 0;
long savePosition = _Base.Length;
do
{
if (_CurrentLine == goToLine)
{
savePosition = _CurrentPosition;
if (stopWhenLine) return _CurrentLine;
}
}
while (ReadLine() != null);
// GoToPosition
int count = _CurrentLine;
_CurrentLine = goToLine;
_Base.Seek(savePosition, SeekOrigin.Begin);
return count;
}
/// <summary>
/// Read Line
/// </summary>
/// <returns></returns>
public string ReadLine()
{
bool found = false;
StringBuilder sb = new StringBuilder();
while (!found)
{
if (_Read <= 0)
{
// Read next block
_Index = 0;
_Read = _Base.Read(_Bff, 0, BufferLength);
if (_Read == 0)
{
if (sb.Length > 0) break;
return null;
}
}
for (int max = _Index + _Read; _Index < max; )
{
char ch = (char)_Bff[_Index];
_Read--; _Index++;
_CurrentPosition++;
if (ch == ' using (StreamLineReader st = new StreamLineReader(File.OpenRead("E:\log.txt")))
{
bool ok = st.GoToLine(1);
int count= st.GetCount(0);
string w0 = st.ReadLine();
string w1 = st.ReadLine();
string w2 = st.ReadLine();
string w3 = st.ReadLine();
}
' || ch == '\n')
{
found = true;
break;
}
else if (ch == '\r') continue;
else sb.Append(ch);
}
}
_CurrentLine++;
return sb.ToString();
}
/// <summary>
/// Free resources
/// </summary>
public void Dispose()
{
if (_Base != null)
{
_Base.Close();
_Base.Dispose();
_Base = null;
}
}
}
Use:
用:
readonly static FieldInfo charPosField = typeof(StreamReader).GetField("charPos", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
readonly static FieldInfo charLenField = typeof(StreamReader).GetField("charLen", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
readonly static FieldInfo charBufferField = typeof(StreamReader).GetField("charBuffer", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
static long ActualPosition(StreamReader reader)
{
var charBuffer = (char[])charBufferField.GetValue(reader);
var charLen = (int)charLenField.GetValue(reader);
var charPos = (int)charPosField.GetValue(reader);
return reader.BaseStream.Position - reader.CurrentEncoding.GetByteCount(charBuffer, charPos, charLen-charPos);
}
回答by Serge Savel
Tracking the actual StreamReader position (in bytes):
跟踪实际的 StreamReader 位置(以字节为单位):
##代码##You are welcome.
不客气。

