Ошибка нехватки памяти при архивировании файла журнала

У меня проблема с консольным заданием, которое запускается и создает ежедневный файл журнала, который я архивирую в полночь.

Это создает пустой файл журнала на следующий день и архивированный файл с вчерашней датой в названии и содержимым старого файла для устранения проблем, которые у меня могли возникнуть и о которых я не знал до следующего дня.

Однако с тех пор, как я приступил к работе с BOT, у меня возникали проблемы с ошибками системной нехватки памяти при попытке заархивировать файл.

Сначала я просто не мог получить заархивированный файл, затем я разработал способ получить по крайней мере последние 100000 строк, что недостаточно.

Заворачиваю все в 3 попытки / ловит

  1. I/O
  2. Системе не хватает памяти
  3. стандартное исключение

Однако это всегда OutOfMemoryException, которое я получаю, например

System.OutOfMemoryException Ошибка: было сгенерировано исключение типа "System.OutOfMemoryException".;

Чтобы дать вам пример размером 100000 строк журнала составляет около 11 МБ файла

Стандартный полный файл журнала может быть от 1/2 ГБ до 2 ГБ.

Что мне нужно знать, это:

а) какой размер стандартного текстового файла приведет к ошибке "недостаточно памяти" при попытке использовать File.ReadAllText или пользовательскую функцию StreamReader, которую я вызываю ReadFileString, например

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

б) это память моего компьютера (у меня 16 ГБ ОЗУ - 8 ГБ во время копирования) или объекты, которые я использую в C#, которые не работают с открытием и копированием файлов.

При архивировании я сначала пытаюсь использовать свою пользовательскую функцию ReadFileString (см. Выше), если она возвращает 0 байт содержимого, я пытаюсь использовать File.ReadAllText, а затем, если это не удается, я пытаюсь использовать пользовательскую функцию для получения последних 100000 строк, чего на самом деле недостаточно для ошибки отладки в начале дня.

Файл журнала начинается в полночь, когда создается новый, и регистрируется весь день. У меня никогда не было ошибок нехватки памяти, но с тех пор, как я увеличил частоту вызовов методов, журналирование расширилось, что означает, что размер файлов также увеличился.

Это моя пользовательская функция для получения последних 100000 строк. Мне интересно, сколько строк я мог бы получить без ИТ, из-за которого не хватало памяти, и я вообще не получил никакого содержимого файла журнала последних дней.

Что люди предлагают для максимального размера файла для различных методов / памяти, необходимых для хранения X строк, и каков наилучший метод для получения как можно большего количества файла журнала?

Например, какой-то способ зацикливания строки за строкой, пока не будет выполнено исключение, и затем сохранение того, что у меня есть.

Это мой метод 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 ответ

Решение

try: сохранить позицию очереди и потока в области видимости, попробуйте GC.Collect() при выходе из памяти исключение и снова вызвать функцию. искать поток до последней позиции и продолжить. или: используйте одну базу данных, такую ​​как sqlite, и сохраняйте новейшие 100000 записей в каждой таблице.

Другие вопросы по тегам