C#在大型文本文件中搜索字符串.如果搜索同一个文件,转到上次读取的行并开始搜索



如果我一天中多次在同一个LOG文件中搜索字符串,那么在上一次搜索中转到文件中读取的最后一行,然后开始逐行读取会更快吗?这里会有什么显著的节省吗?

示例文件

过程ID逻辑

11111在中间层服务器上运行一些愚蠢的逻辑。

11111仍在运行逻辑

22222从另一个用户在中间层服务器上运行一些愚蠢的逻辑。

哦,看,第一道工序完成了。

22222第二进程上仍在运行逻辑。

有时我想要上一次加载文件后的许多行。目前我使用UltraEdit加载一次文件,然后更新文件,但这仍然需要相当长的时间。

在上面的这个例子中,我想要第一个过程中的任何一行。

注意:

  1. 文件的大小有时可以达到几百MB
  2. 上面的例子是缩写,每个进程ID可以包含100’s的逻辑行
  3. 我正在通过网络访问日志文件。我发现,使用UE,通过网络加载文件然后继续更新文件比复制到本地PC然后打开文件更快
  4. 我希望有一个C#控制台应用程序,可以从powershell运行,并通过管道将我想要的行发送到屏幕或文件

我的另一个问题是,如何使这个过程尽可能高效?1.关于用于我的文件大小的C#方法?2.关于用于编写实用程序的应用程序?我有powershell、C#、C++、perl

使用Stream.Seek可以做到这一点。您只需要记住流中的最后一个位置,然后从那里向前移动。如果你的日志文件只添加行,这会很好,而且肯定比一遍又一遍地读取和扫描同一行更快。

如果你发布一些你现有的代码,我甚至可以帮你写代码来做这件事

http://msdn.microsoft.com/en-us/library/system.io.stream.seek.aspx

我想自己实现这样的东西,所以我花了一些时间尝试一下。以下是我提出的FileStream的扩展方法(您必须将其放在一个静态类中):

public static string ReadLineAndCountPosition(this FileStream fs, ref long position)
{
//Check if too great a position was passed in:
if (position > fs.Length)
return null;
bool is_carriage_return = false;
StringBuilder sb = new StringBuilder();
fs.Seek(position, SeekOrigin.Begin);
while (position < fs.Length)
{
var my_byte = fs.ReadByte();
position++;
//Check for newlines
if (is_carriage_return && my_byte == 10)// n
return sb.ToString();
if (my_byte == 13)                     // r
is_carriage_return = true;
else
{
is_carriage_return = false;
sb.Append((char)my_byte);
}
}
return sb.ToString();//We've consumed the entire file.
}

要使用它,您可以使用ReadLineAndCountPosition,只需调用它并传递一个long参数,我们将在其中保存位置。稍后,我们将简单地.Seek()到此位置。

static void Main(string[] args)
{
FileStream fs = new FileStream("testfile.txt",FileMode.Open);
long saved_position = 0;
while(true)
{
string current_line = fs.ReadLineAndCountPosition(ref saved_position);
if (current_line == null || current_line == "SomeSearchString")
break;
}
//Some time later we want to search from the saved position:
while(true)
{
string current_line = fs.ReadLineAndCountPosition(ref saved_position);
if (current_line == null || current_line == "SecondSearchString")
break;
}
}

我自己做了几次测试,结果似乎很好。如果你有任何麻烦,请告诉我。希望它能帮助你。

最新更新