1

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

示例文件

进程标识逻辑

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

11111 仍在运行逻辑

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

11111 哦看第一个过程完成了。

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

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

在上面的这个例子中,我想要从第一个进程开始。

笔记:

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

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

4

2 回答 2

1

使用 Stream.Seek 可以做到这一点。您只需要记住流中的最后一个位置是什么,然后从那里继续前进。如果您的日志文件只向其中添加行,这将工作得很好,而且它肯定会比一遍又一遍地读取和扫描相同的行更快。

如果您发布一些现有代码,我什至可以帮助您编写代码来完成它。

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

于 2012-12-15T23:38:45.960 回答
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我们将保存位置的参数来使用它。稍后我们将简单地 .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;
    }
}

我自己进行了一些测试,它似乎运行良好。如果您有任何麻烦,请告诉我。希望它可以帮助你。

于 2012-12-15T23:57:27.277 回答