Учебник по Delphi 4

Запись в Log-файл



    Запись отладочной информации в файл протокола (Log-файл) существенно отличается от предыдущих приемов записи, так как это уже нельзя назвать "быстро и грязно". Это отличная технология, которую можно использовать в любом приложении.


    Запись в файл протокола выполняется так же, как и вывод на консоль, но вместо WriteLn (. . . ) используется WriteLn (LogFile, . . . ), где LogFile — имя файловой переменной типа TextFile. Надо также не забывать открывать этот файл в начале работы приложения и закрывать — в конце. Проще всего этого добиться, поместив соответствующий код в свой модуль, который благодаря возможности условной компиляции подключается только в отладочной версии вашей программы.

Листинг 2.1. Модуль протоколирования отладочной информации.

    unit uLoq;


    interface


    procedure Log(S: Strings-implementation uses


        Windows, SysUtils;


    var


        LogFile: TextFile;


        LogCriticalSection: TRtlCriticalSection;


    procedure Log(S: String);


    var


        SystemTime: TSystemTime;




        FileTime: TFileTime;


    begin


        GetSystemTime (SystemTime) ;


        SystemTimeToFileTime(SystemTime, FileTime) ;


        EnterCriticalSection(LogCriticalSection);


        WriteLn(LogFile, Format('%s %.8x%.8x %5',


            [FormatDateTime('yy.mm.dd hh.inm.ss'. Now),


            FileTime.dwHighDateTime, FileTime.dwLowDateTime, S])) ;


        LeaveCriticalSection(LogCriticalSection) ;



    end;

    procedure Startup;

    var

        FileName: String;

    begin

        InitializeCriticalSection(LogCriticalSection);

        FileName := Format("Log file for %s at %s.txf,

            [ParamStr(O), DateTimeToStr(Now)]) ;

        while Pos(':', FileName) 0 do

            FileName[Pos(':', FileName)] := '.';

        while Pos('/', FileName) 0 do

            FileName[Pos('/', FileName)] := '-';

        while Pos('\', FileName) 0 do

            FileName[Pos('\', FileName)] := '.';

        AssignFile(LogFile, FileName);

        Rewrite(LogFile) ;

    end;

    procedure Shutdown;

    begin

        CloseFile(LogFile) ;

        DeleteCriticalSection(LogCriticalSection) ;

    end;

    initialization Startup;

    finalization Shutdown;

end.

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

    unit MyUnit;
    interface
    uses
        ($ifdef Debug} uLog, {$endif)
        Windows, Messages, SysUtils, Classes,
        . . .



    Затем используйте его приблизительно так.

    {$ifdef Debug)

    Log(Format(' Entering the Foo procedure; Bar = %d',[Bar]));

    {$endif}

    He забывайте размещать вызов между директивами условной компиляции, иначе при компиляции коммерческой версии возникнет ошибка.

    Модуль uLog обладает двумя интересными и полезными свойствами. Во-первых, каждая запись в файл предваряется информацией о дате, времени и шестнадцатеричным числом, соответствующим системному времени в миллисекундах. Эта информация может быть весьма полезной, особенно когда вы хотите отследить последовательность событий в приложении. Во-вторых, модуль использует критические разделы (critical section), что обеспечивает доступ к файлу только одной подзадачи в один момент времени.

    На рис. 2.25 показан типичный файл протокола в программе Notepad.

 


Рис. 2.25. Пример отладочного файла протокола

    Как правильно использовать файл протокола? Какую информацию в него записывать? Сколько программистов, столько и ответов на эти вопросы. Лично я предпочитаю придерживаться золотой середины между "записывай все" и "записывай только то, что отлаживаешь".


Содержание раздела