Хранение файлов журнала под определенным размером - PullRequest
7 голосов
/ 20 января 2011

У меня есть приложение, которое работает на автономном ПК в киоске (C # / WPF). Он выполняет некоторые типичные операции записи в текстовый файл. На ПК имеется ограниченный объем дискового пространства для хранения этих журналов по мере их роста.

Что мне нужно сделать, так это уметь указать максимальный размер файла журнала. Если при попытке записи в журнал превышен максимальный размер, новые данные будут записаны в конец журнала, а самые старые данные будут удалены с самого начала.

Получение размера файла не проблема, но есть ли какие-либо типичные методы манипулирования файлами, чтобы сохранить файл под определенным размером?

Ответы [ 6 ]

15 голосов
/ 20 января 2011

Один из способов справиться с этим - иметь два файла журнала, каждый из которых имеет половину максимального размера.Вы просто вращаетесь между ними, когда достигаете максимального размера каждого файла.Поворот к файлу приводит к тому, что он перезаписывается новым файлом.

Встроенная функция ведения журнала, такая как log4net, имеет встроенную функциональность.

5 голосов
/ 20 января 2011

Попробуйте использовать Log4Net

http://www.codeproject.com/KB/aspnet/log4net.aspx

4 голосов
/ 20 января 2011

Нет простого способа удалить данные из начала файла. Итак, у вас есть несколько вариантов:

  1. Храните журнал в нескольких меньших файлах журнала и удаляйте самые старые «куски», если общий размер всех файлов журнала превышает ваш лимит. Это похоже на то, что вы хотите сделать, но на другом уровне
  2. Переименуйте файл журнала в «log.date» и запустите новый журнал. Аналогично (1), но не вариант, если у вас ограниченное дисковое пространство.
  3. Если у вас достаточно ОЗУ и размер вашего журнала относительно мал, чтобы поместиться в памяти, вы можете сделать следующее: отобразить весь файл в память, используя файл с отображением в памяти, затем выполнить операцию перемещения, взяв данные из середины файл и перемещение их в начало. Затем обрежьте файл. Это единственный способ легко удалить данные из начала файла журнала, не создавая их копию.
2 голосов
/ 20 января 2011

Linux OS: проверить logrotate - http://www.cyberciti.biz/faq/how-do-i-rotate-log-files/

Windows os: попробуйте поискать в Google logrotate. например: http://blog.arithm.com/2008/02/07/windows-log-file-rotation/

0 голосов
/ 08 февраля 2019

Я тоже хотел простое решение, но я не хотел добавлять другую зависимость, поэтому я сделал простой метод. Здесь есть все, что вам нужно, кроме части сжатия старого файла в zip-файл, который вы можете найти здесь: Создать zip-файл в памяти из байтов (текст с произвольной кодировкой)

static int iMaxLogLength = 2000; // Probably should be bigger, say 200,000
static int KeepLines = 5; // minimum of how much of the old log to leave

public static void ManageLogs(string strFileName)
{
    try
    {
        FileInfo fi = new FileInfo(strFileName);
        if (fi.Length > iMaxLogLength) // if the log file length is already too long
        {
            int TotalLines = 0;
                var file = File.ReadAllLines(strFileName);
                var LineArray = file.ToList();
                var AmountToCull = (int)(LineArray.Count - KeepLines);
                var trimmed = LineArray.Skip(AmountToCull).ToList();
                File.WriteAllLines(strFileName, trimmed);
                string archiveName = strFileName + "-" + DateTime.Now.ToString("MM-dd-yyyy") + ".zip";
                File.WriteAllBytes(archiveName, Compression.Zip(string.Join("\n", file)));
        }

    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed to write to logfile : " + ex.Message);
    }
}

У меня это есть в разделе инициализации / повторной инициализации моего приложения, поэтому оно запускается несколько раз в день.

ErrorLogging.ManageLogs("Application.log");
0 голосов
/ 08 июня 2017

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

// This is how to call it
private void buttonLog_Click(object sender, EventArgs e)
{
    c_Log.writeToFile(textBoxMessages.Text, "../../log.log", 1);
}


public static class c_Log
{
    static int iMaxLogLength = 15000; // Probably should be bigger, say 200,000
    static int iTrimmedLogLength = -1000; // minimum of how much of the old log to leave

    static public void writeToFile(string strNewLogMessage, string strFile, int iLogLevel)
    {
        try
        {
            FileInfo fi = new FileInfo(strFile);

            Byte[] bytesSavedFromEndOfOldLog = null;

            if (fi.Length > iMaxLogLength) // if the log file length is already too long
            {
                using (BinaryReader br = new BinaryReader(File.Open(strFile, FileMode.Open)))
                {
                    // Seek to our required position of what you want saved.
                    br.BaseStream.Seek(iTrimmedLogLength, SeekOrigin.End);

                    // Read what you want to save and hang onto it.
                    bytesSavedFromEndOfOldLog = br.ReadBytes((-1 * iTrimmedLogLength));
                }
            }

            byte[] newLine = System.Text.ASCIIEncoding.ASCII.GetBytes(Environment.NewLine);

            FileStream fs = null;
            // If the log file is less than the max length, just open it at the end to write there
            if (fi.Length < iMaxLogLength) 
                fs = new FileStream(strFile, FileMode.Append, FileAccess.Write, FileShare.Read);
            else // If the log file is more than the max length, just open it empty
                fs = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read);

            using (fs)
            {
                // If you are trimming the file length, write what you saved. 
                if (bytesSavedFromEndOfOldLog != null)
                {
                    Byte[] lineBreak = Encoding.ASCII.GetBytes("### " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " *** *** *** Old Log Start Position *** *** *** *** ###");
                    fs.Write(newLine, 0, newLine.Length);
                    fs.Write(newLine, 0, newLine.Length);
                    fs.Write(lineBreak, 0, lineBreak.Length);
                    fs.Write(newLine, 0, newLine.Length);
                    fs.Write(bytesSavedFromEndOfOldLog, 0, bytesSavedFromEndOfOldLog.Length);
                    fs.Write(newLine, 0, newLine.Length);
                }
                Byte[] sendBytes = Encoding.ASCII.GetBytes(strNewLogMessage);
                // Append your last log message. 
                fs.Write(sendBytes, 0, sendBytes.Length);
                fs.Write(newLine, 0, newLine.Length);
            }
        }
        catch (Exception ex)
        {
            ; // Nothing to do...
              //writeEvent("writeToFile() Failed to write to logfile : " + ex.Message + "...", 5);
        }
    }
}
...