繁体   English   中英

C#OutofMemoryException与Regex

[英]C# OutofMemoryException with Regex

我在收到OutOfMemoryException

if (Regex.IsMatch(output, @"^\\d"))

但是我不确定是什么原因,我的程序已经运行了大约4分钟。 读取文本文件(很多)。 将它们批量插入SQL。 当时的输出字符串没有什么特别的,是从.txt文件读取的一小段文本。

我假设这是由于需要进行正则表达式检查的次数而发生的,在4分钟后它达到了百万次。 有没有办法防止内存问题? 开始循环之前要处理还是清除? 如果是这样,那你怎么办?

编辑:我没有读一个大文件,我正在读很多文件。 失败时,它已经读取了大约6666个文件(5个文件夹),但总共需要读取60个文件夹-> 80.361 .txt文件

编辑:添加了源代码。 希望澄清

更新:

添加:静态void DisposeAll(IEnumerable集)

static void DisposeAll(IEnumerable set)
{
    foreach (Object obj in set)
    {
        IDisposable disp = obj as IDisposable;
        if (disp != null) { disp.Dispose(); }
    }
}

我正在文件夹的每个循环的末尾执行此操作。

DisposeAll(ListExtraInfo);
DisposeAll(ListFouten);
ListFouten.Clear();
ListExtraInfo.Clear();

错误位置已更改,不再是正则表达式,而是ListFouten现在引起了它。 仍然发生在读取大约6666 .txt文件的情况。

引发了类型为'System.OutOfMemoryException'的异常。

static void Main(string[] args)
        {
            string pathMMAP = @"G:\HLE13\Resultaten\MMAP";
            string[] entriesMMAP = Directory.GetDirectories(pathMMAP);
            List<string> treinNamen = new List<string>();

            foreach (string path in entriesMMAP)
            {
                string TreinNaam = new DirectoryInfo(path).Name;
                treinNamen.Add(TreinNaam);
                int IdTrein = 0;
                ListExtraInfo = new List<extraInfo>();
                ListFouten = new List<fouten>();
                readData(TreinNaam, IdTrein, path);
             }
        }


        static void readData(string TreinNaam, int IdTrein, string path)
        {
            using (SqlConnection sourceConnection = new SqlConnection(GetConnectionString()))
            {
                sourceConnection.Open();


                try
                {
                    SqlCommand commandRowCount = new SqlCommand(
                 "SELECT TreinId FROM TestDatabase.dbo.Treinen where Name = " + TreinNaam,
                 sourceConnection);
                    IdTrein = Convert.ToInt16(commandRowCount.ExecuteScalar());

                }
                catch (Exception ex)
                {


                }

            }

            string[] entriesTreinen = Directory.GetDirectories(path);
            foreach (string rapport in entriesTreinen)
            {

                string RapportNaam = new DirectoryInfo(rapport).Name;
                FileInfo fileData = new System.IO.FileInfo(rapport);

                leesTxt(rapport, TreinNaam, GetConnectionString(), IdTrein);

            }
        }
        public static string datum;
        public static string tijd;
        public static string foutcode;
        public static string absentOfPresent;
        public static string teller;
        public static string omschrijving;
        public static List<fouten> ListFouten;
        public static List<extraInfo> ListExtraInfo;
        public static string textname;
        public static int referentieGetal = 0;


        static void leesTxt(string rapport, string TreinNaam, string myConnection, int TreinId)
        {
            foreach (string textFilePath in Directory.EnumerateFiles(rapport, "*.txt"))
            {

                textname = Path.GetFileName(textFilePath);
                textname = textname.Substring(0, textname.Length - 4);

                using (StreamReader r = new StreamReader(textFilePath))
                {
                    for (int x = 0; x <= 10; x++)
                        r.ReadLine();

                    string output;

                    Regex compiledRegex = new Regex(@"^\d", RegexOptions.Compiled);
                    string[] info = new string[] { };
                    string[] datumTijdelijk = new string[] { };

                    while (true)
                    {

                        output = r.ReadLine();
                        if (output == null)
                            break;


                        if (compiledRegex.IsMatch(output))
                        {
                            info = output.Split(' ');
                            int kolom = 6;
                            datum = info[0];
                            datumTijdelijk = datum.Split(new[] { '/' });


                            try
                            {
                                datum = string.Format("{2}/{1}/{0}", datumTijdelijk);
                                tijd = info[1];
                                foutcode = info[2];
                                absentOfPresent = info[4];
                                teller = info[5];
                                omschrijving = info[6];
                            }
                            catch (Exception ex)
                            {

                            }


                            while (kolom < info.Count() - 1)
                            {
                                kolom++;
                                omschrijving = omschrijving + " " + info[kolom];
                            }
                            referentieGetal++;


                            ListFouten.Add(new fouten { Date = datum, Time = tijd, Description = omschrijving, ErrorCode = foutcode, Module = textname, Name = TreinNaam, TreinId = TreinId, FoutId = referentieGetal });

                        }


                        if (output == string.Empty)
                        {
                            output = " ";
                        }
                        if (Char.IsLetter(output[0]))
                        {
                            ListExtraInfo.Add(new extraInfo { Values = output, FoutId = referentieGetal });
                        }

                    }

                }

            }

        }

可能是因为您的代码每次使用时都会重新编译正则表达式吗? 尝试改用已编译的Regex转换 foreach循环之外,存储已编译的Regex变量:

Regex compiledRegex = new Regex(@"^\d", RegexOptions.Compiled);

然后,在检查匹配项时,请使用:

if (compiledRegex.IsMatch(output))

编辑:此答案无效。 尽管这里的Regex文档指出实例方法中遇到的Regex表达式将被重新编译,但事实并非如此:它们被缓存了。

这个问题不是正则表达式操作的错误,因为真正的错误在于最终在正则表达式处理周围存储的数据。

打个比方是开汽车,然后说:“当我打开收音机时,它的汽油用完了”。 这不是收音机的错...

我建议您确定为什么要存储如此大量的数据并加以解决。


有比将所有内容都扔到内存中更好的处理和分析信息的方法。 我相信您将需要重写逻辑以实现最终目标。

为什么要收集,更重要的是保存有关6000多个文件的每一行的信息? 这可能是这里的真正问题。


否则,请主动执行以下步骤

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM