【问题标题】:How to Speed Up Reading a File using FileSteam如何使用 FileStream 加速读取文件
【发布时间】:2015-09-25 21:57:42
【问题描述】:

我在搜索文件内容时遇到性能问题。我正在使用 FileStream 类来读取文件(每次搜索将涉及约 10 个文件,每个文件的大小约为 70 MB)。但是,在我的搜索过程中,所有这些文件都同时被另一个进程访问和更新。因此,我不能使用Buffersize 来读取文件。即使我使用的是正则表达式,在StreamReader 中使用缓冲区大小也需要 3 分钟。

有没有人遇到过类似的情况并可以提供任何关于提高文件搜索性能的建议?

代码片段

  private static int BufferSize = 32768;
  using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {

            using (TextReader txtReader = new StreamReader(fs, Encoding.UTF8, true, BufferSize))

            {
                System.Text.RegularExpressions.Regex patternMatching = new System.Text.RegularExpressions.Regex(@"(?=\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})(.*?)(?=\n\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                System.Text.RegularExpressions.Regex dateStringMatch = new Regex(@"^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}");
                char[] temp = new char[1048576];
                while (txtReader.ReadBlock(temp, 0, 1048576) > 0)
                {
                    StringBuilder parseString = new StringBuilder();
                    parseString.Append(temp);
                    if (temp[1023].ToString() != Environment.NewLine)
                    {
                        parseString.Append(txtReader.ReadLine());
                        while (txtReader.Peek() > 0 && !(txtReader.Peek() >= 48 && txtReader.Peek() <= 57))
                        {
                            parseString.Append(txtReader.ReadLine());
                        }
                    }
                    if (parseString.Length > 0)
                    {
                        string[] allRecords = patternMatching.Split(parseString.ToString());
                        foreach (var item in allRecords)
                        {

                            var contentString = item.Trim();
                            if (!string.IsNullOrWhiteSpace(contentString))
                            {
                                var matches = dateStringMatch.Matches(contentString);
                                if (matches.Count > 0)
                                {

                                    var rowDatetime = DateTime.MinValue;
                                    if (DateTime.TryParse(matches[0].Value, out rowDatetime))
                                    {
                                        if (rowDatetime >= startDate && rowDatetime < endDate)
                                        {
                                            if (contentString.ToLowerInvariant().Contains(searchText))
                                            {
                                                var result = new SearchResult
                                                {
                                                    LogFileType = logFileType,
                                                    Message = string.Format(messageTemplateNew, item),
                                                    Timestamp = rowDatetime,
                                                    ComponentName = componentName,
                                                    FileName = filePath,
                                                    ServerName = serverName
                                                };
                                                searchResults.Add(result);
                                            }
                                        }
                                    }

                                }

                            }
                        }
                    }
                }
            }
        }

        return searchResults;

【问题讨论】:

  • 您说多个文件正在被多个进程访问和更新,您是如何解决并发问题的?
  • 嗨,Yacoub,我目前的搜索并不关心文件中的任何未来更新。我只需要打开该文件并使用当前可用的字符串搜索它。
  • 嵌套的 ifs 数量太可怕了 --- 计划结合其中一些条件吗?

标签: c# performance stream filestream


【解决方案1】:

前段时间,我不得不分析许多 FileZilla 服务器日志文件,每个文件 >120MB。 我使用一个简单的列表来获取每个日志文件的所有行,然后在搜索特定行时表现出色。

List<string> fileContent = File.ReadAllLines(pathToFile).ToList()

但在您的情况下,我认为性能不佳的主要原因不是读取文件。尝试对循环的某些部分进行 StopWatch 以检查花费最多时间的位置。如果在像您这样的循环中多次使用 Regex 和 TryParse,可能会非常耗时。

【讨论】:

  • 其实我的日志文件格式不一样。
  • 我需要将文件从一个匹配模式读取到另一个匹配模式。匹配专利并不总是在同一条线上。匹配的模式字符串中有换行符。所以我需要使用 RegEx 来识别匹配标准。可能我需要找出优化正则表达式以提高性能的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 2011-04-21
相关资源
最近更新 更多