从与 C# 中的正则表达式匹配的 StreamReader 获取行的有效方法

Efficient Way To Get Line from StreamReader which Matches Regex in C#

我有一个文件,我想获取与正则表达式查询匹配的文件行。

我的代码是这样的:

Assembly assembly = typeof(EmbeddedResourceGetter).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream(resourcePath);
StreamReader sr = new StreamReader(stream);

return file.ReadToEnd()
    .Split('\n').ToList()
    .Find(l => Regex.IsMatch(l, "regex-query-here"));

但是,我觉得这样效率很低,如果我需要重复多次,可能需要很长时间才能完成。

那么有没有更有效的方法来获取与正则表达式查询匹配的行而不读取整个文件,或者我是否必须以不同的方式重构我的代码以使其更有效?

你应该读取文件一次,将它存储在一个变量中,因为 I/O 操作是昂贵的。然后,运行 变量的正则表达式。

当您将文件读入变量时,您将其从硬盘读取到 RAM,访问 RAM 很快,硬盘很慢。 毫无疑问最好是从硬盘读取一次!

如果你想匹配多行模式,逐行读取也会失败。

例如:

Can
you
match
me
if
you
read
me
line
by
line?

"Can\s+you" 正则表达式在这种情况下将无法匹配,因为您不会在同一字符串中得到 "Can" 和 "you"。

Find 只得到第一个匹配项。因此,如果您真的想获得第一场比赛,请不要阅读整个文件。它效率低下。使用 File.ReadLines

逐行读取文件

在每次迭代中使用 Regex.IsMatch 也是低效的。只创建一次正则表达式。

Regex regex = new Regex("regex-query-here");
return File.ReadLines(path).FirstOrDefault(l => regex.IsMatch(l));

File.ReadLines 一次只加载一行到内存。 FirstOrDefault 将在找到第一个匹配项后立即停止迭代。因此,如果您的匹配项位于第 23 行,您将仅从文件中读取 23 行,您将获得结果。

将所有文件读入内存可能会更快,但这是内存和性能之间的权衡。

我必须提到的另一件事是,按 \n 拆分并不是跨平台获取行的方式。