内存不足错误归档日志文件

时间:2016-04-08 16:54:46

标签: c# .net memory io readfile

我遇到了运行控制台作业的问题,并创建了我在午夜归档的每日日志文件。

这会在第二天创建一个空白日志文件,并在名称和旧文件的内容中创建一个带有昨天日期的归档文件,用于调试我可能已经知道的问题,直到第二天才知道。

然而,自从我开始完成BOT的工作以来,当我尝试归档文件时,我遇到了系统内存不足错误的问题。

起初我根本无法获得存档文件,然后我找到了至少获得最后10万行的方法,这还不够。

我将所有内容包装在3次尝试/捕获中

  1. I / O
  2. 系统内存不足
  3. 标准例外
  4. 然而,我总是得到OutOfMemoryException,例如

    System.OutOfMemoryException错误:抛出了类型'System.OutOfMemoryException'的异常。;

    为您举例说明100,000行日志大小约为11MB文件

    标准的完整日志文件可以是1/2 GB到2 GB

    的任何内容

    我需要知道的是:

    a)当尝试使用File.ReadAllText或我调用ReadFileString的自定义StreamReader函数时,标准文本文件的大小会引发内存不足错误,例如

    public static string ReadFileString(string path)
    {
        // Use StreamReader to consume the entire text file.
    using (StreamReader reader = new StreamReader(path))
    {
        return reader.ReadToEnd();
        }
    }
    

    b)它是我的计算机内存(我有16GB内存 - 复制时使用8GB)或我在C#中使用的文件打开和复制失败的对象。

    归档时我首先尝试使用我的自定义ReadFileString函数(见上文),如果返回0字节的内容我尝试File.ReadAllText然后如果失败我尝试自定义函数来获取最后100,000行,这是真的还不足以在当天早些时候调试错误。

    日志文件从午夜开始,当时创建一个新日志并记录全天。我从来没有用过内存错误但是因为我已经调高了方法调用的频率,所以日志记录已经扩展,这意味着文件大小也一样。

    这是我获取最后100,000行的自定义函数。我想知道在没有IT丢失内存错误的情况下我可以获得多少行,而且我根本没有得到最后几天日志文件的任何内容。

    对于保存X行所需的各种方法/内存的最大文件大小,人们建议什么?获取尽可能多的日志文件的最佳方法是什么?

    E.G一些逐行循环的方法,直到遇到异常,然后保存我所拥有的东西。

    这是我的GetHundredThousandLines方法,它记录到一个非常小的调试文件,这样我就可以看到在归档过程中发生了什么错误。

    private bool GetHundredThousandLines(string logpath, string archivepath)
    {
        bool success = false;
    
        int numberOfLines = 100000;
    
    
        if (!File.Exists(logpath))
        {
        this.LogDebug("GetHundredThousandLines - Cannot find path " + logpath + " to archive " + numberOfLines.ToString() + " lines");
        return false;
        }
    
        var queue = new Queue<string>(numberOfLines);
    
        using (FileStream fs = File.Open(logpath, FileMode.Open, FileAccess.Read, FileShare.Read))
        using (BufferedStream bs = new BufferedStream(fs))  // May not make much difference.
        using (StreamReader sr = new StreamReader(bs))
        {
        while (!sr.EndOfStream)
        {
            if (queue.Count == numberOfLines)
            {
            queue.Dequeue();
            }
    
            queue.Enqueue(sr.ReadLine() + "\r\n");
        }
        }
    
        // The queue now has our set of lines. So print to console, save to another file, etc.
        try
        {
    
        do
        {        
            File.AppendAllText(archivepath, queue.Dequeue(), Encoding.UTF8);
        } while (queue.Count > 0);
    
    
        }
        catch (IOException exception)
        {
        this.LogDebug("GetHundredThousandLines - I/O Error accessing daily log file with ReadFileString: " + exception.Message.ToString());
        }
        catch (System.OutOfMemoryException exception)
        {
        this.LogDebug("GetHundredThousandLines - Out of Memory Error accessing daily log file with ReadFileString: " + exception.Message.ToString());
        }
        catch (Exception exception)
        {
        this.LogDebug("GetHundredThousandLines - Exception accessing daily log file with ReadFileString: " + exception.Message.ToString());
        }
    
    
        if (File.Exists(archivepath))
        {
        this.LogDebug("GetHundredThousandLines - Log file exists at " + archivepath);
        success = true;
        }
        else
        {
        this.LogDebug("GetHundredThousandLines - Log file DOES NOT exist at " + archivepath);
        }
    
        return success;
    
    }
    

    非常感谢任何帮助。

    由于

1 个答案:

答案 0 :(得分:-1)

尝试: 保持队列和流在类范围内的位置,在出现内存不足和再次调用函数时尝试GC.Collect()。寻求流到最后的位置并继续。 要么: 使用像sqlite这样的数据库,并在每个表中保留最新的100000条记录。