C#在大文本文件中搜索字符串。如果您搜索上次阅读的同一文件转到行并开始搜索

时间:2012-12-15 22:31:46

标签: c# string search

如果我在同一天的LOG文件中多次搜索字符串会以某种方式更快地以某种方式转到上一次搜索文件中读取的最后一行,然后开始逐行阅读?这里会有大笔节省吗?

示例文件

进程ID逻辑

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

11111仍在运行逻辑

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

11111哦,看看第一个过程已经完成。

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

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

在上面这个例子中,我希望从第一个过程开始。

注意:

  1. 文件有时可以是几百MB。
  2. 上面的例子是缩写的,每个进程ID可能包含100'的逻辑行。
  3. 我正在通过网络访问日志文件。我发现使用UE可以更快地从网络加载文件然后继续更新文件,而不是复制到我的本地PC然后打开它。
  4. 我希望有一个C#控制台应用程序,可以从powershell运行并将我想要的行传输到屏幕或文件。
  5. 我的另一个问题是什么能使这个过程尽可能高效? 1.关于用于我的文件大小的C#方法? 2.关于用于编写实用程序的应用程序?我有powershell,C#,C ++,perl

2 个答案:

答案 0 :(得分:1)

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

如果您发布一些现有代码,我甚至可以帮助您编写代码来执行此操作。

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

答案 1 :(得分:1)

我自己想要实现这样的东西,所以我花了一些时间来试一试。这是一个扩展方法(你必须把它放在一个静态类中)到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参数,我们将保存位置。我们将简单地。查询()到这个位置一段时间后面。

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;
    }
}

我自己做了一些测试,似乎工作得很好。如果您有任何问题,请告诉我。希望它可以帮助你。