Счетчик HotLog

На главнуюЧто я делаю...Программы автора и не только...Творчество
Статьи автораКнига отзывов и предложенийОбо мне, любимомФотоальбом

 
 

Trailing Space Remover

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

Файл проекта весьма лаконичен:

program TrailingSpaceRemover;

{$APPTYPE CONSOLE}

uses
  MPTrailingSpaceRemover in 'MPTrailingSpaceRemover.pas';

begin
  TMPTrailingSpaceRemover.Run;
end.

Здесь производится вызов классовой процедуры Run. Обратимся теперь к модулю класса TMPTrailingSpaceRemover.

// Модуль класса удаления ведомых пробелов.
unit MPTrailingSpaceRemover;

interface

uses
  Classes, SysUtils;

type
  // Класс исключений удаления ведомых пробелов.
  ETrailingSpaceRemoverException = class(Exception);

  // Класс удаления ведомых пробелов.
  TMPTrailingSpaceRemover = class(TObject)
  private
    // Содержимое файла.
    FFileContent: TStringList;
    // Имя файла.
    FFileName: String;
    // Обработать параметры запуска.
    procedure ProcessCommandLine;
    // Вывести справку по программе.
    procedure ShowHelpString;
    // Проверить файл.
    procedure CheckFile;
    // Обработать файл.
    procedure ProcessContent;
  public
    { TObject }
    constructor Create;
    destructor Destroy; override;
    // Выполнить.
    class procedure Run;
  end;

implementation

uses
  Windows;

const
  // Ключ показа справки по программе.
  HELP_SWITCH = '?';

resourcestring
  // Строка помощи по программе.
  HELP_STRING_TEMPLATE =
    'Утилита удаления ведомых пробелов.' + sLineBreak +
    sLineBreak + '%s file' +
    sLineBreak + '  file       Имя текстового файла.';
  // Файл не найден.
  E_FILE_NOT_FOUND = 'Файл "%s" не найден';
  // Параметры запуска не найдены.
  E_PARAMS_NOT_FOUND = 'Не заданы параметры запуска';

// Вывести на консоль строку.
procedure WriteStringToConsole(
  // Строка.
  Str: String); forward;

procedure WriteStringToConsole(Str: String);
var
  ResultStr: String;
begin
  if Str <> EmptyStr then
  begin
    SetLength(ResultStr, Length(Str));
    CharToOem(PChar(Str), PChar(ResultStr));
    Writeln(ResultStr);
  end;
end;

{ TMPTrailingSpaceRemover }

procedure TMPTrailingSpaceRemover.CheckFile;
var
  Path: String;
begin
  Path := ExtractFilePath(FFileName);
  if Path = EmptyStr then
    FFileName := ExtractFilePath(ParamStr(0)) + FFileName;
  if not FileExists(FFileName) then
  begin
    WriteStringToConsole(Format(E_FILE_NOT_FOUND, [FFileName]));
    raise ETrailingSpaceRemoverException.CreateFmt(E_FILE_NOT_FOUND, [FFileName]);
  end;
end;

constructor TMPTrailingSpaceRemover.Create;
begin
  inherited Create;
  FFileContent := TStringList.Create;
end;

destructor TMPTrailingSpaceRemover.Destroy;
begin
  FFileContent.Free;
  inherited Destroy;
end;

procedure TMPTrailingSpaceRemover.ProcessCommandLine;
begin
  if (ParamCount = 0) or FindCmdLineSwitch(HELP_SWITCH) then
    ShowHelpString
  else
    FFileName := ParamStr(1);
end;

procedure TMPTrailingSpaceRemover.ProcessContent;
var
  I: Integer;
begin
  with FFileContent do
    for I := 0 to Count - 1 do
      Strings[I] := TrimRight(Strings[I]);
end;

class procedure TMPTrailingSpaceRemover.Run;
begin
  with TMPTrailingSpaceRemover.Create do
  try
    try
      ProcessCommandLine;
      CheckFile;
      FFileContent.LoadFromFile(FFileName);
      ProcessContent;
      FFileContent.SaveToFile(FFileName);
    except
      on E: ETrailingSpaceRemoverException do
        // Ничего не делать.
      else
        raise;
    end;
  finally
    Free;
  end;
end;

procedure TMPTrailingSpaceRemover.ShowHelpString;
begin
  WriteStringToConsole(Format(HELP_STRING_TEMPLATE,
    [UpperCase(ChangeFileExt(ExtractFileName(Paramstr(0)), EmptyStr))]));
  raise ETrailingSpaceRemoverException.Create(E_PARAMS_NOT_FOUND);
end;

end.

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

1. Процедура WriteStringToConsole. Параметр в нее лучше передавать как константу:

// Вывести на консоль строку.
procedure WriteStringToConsole(
  // Строка.
  const Str: String); forward;

procedure WriteStringToConsole(const Str: String);
var
  ResultStr: String;
begin
  if Str <> EmptyStr then
  begin
    SetLength(ResultStr, Length(Str));
    CharToOem(PChar(Str), PChar(ResultStr));
    Writeln(ResultStr);
  end;
end;

2. Если в процессе выполнения происходит исключение, то это результируется таким окном (обрабатываемый файл содержит атрибут Только чтение):

Окно сообщения о необработанном исключении

Связано это с отсутствием глобального обработчика исключений. Поэтому следует немного изменить код, чтобы возникающее исключение выходило красиво.

resourcestring
  // Сообщение о необработанном исключении.
  E_UNHANDLED_EXCEPTION_OCCURED = 'При работе программы возникло исключение %s: %s';

procedure TMPTrailingSpaceRemover.CheckFile;
var
  Path: String;
begin
  Path := ExtractFilePath(FFileName);
  if Path = EmptyStr then
    FFileName := ExtractFilePath(ParamStr(0)) + FFileName;
  if not FileExists(FFileName) then
    raise ETrailingSpaceRemoverException.CreateFmt(
      E_FILE_NOT_FOUND, [FFileName]);
end;

class procedure TMPTrailingSpaceRemover.Run;
begin
  with TMPTrailingSpaceRemover.Create do
  try
    try
      ProcessCommandLine;
      CheckFile;
      FFileContent.LoadFromFile(FFileName);
      ProcessContent;
      FFileContent.SaveToFile(FFileName);
    except
      on E: Exception do
        if E is ETrailingSpaceRemoverException then
          WriteStringToConsole(E.Message)
        else
          WriteStringToConsole(
            Format(E_UNHANDLED_EXCEPTION_OCCURED, [E.ClassName, E.Message]));
    end;
  finally
    Free;
  end;
end;

Теперь все ошибки обрабатываются в одном месте, сообщения обо всех ошибках выводятся также в одном месте. "Наши" исключения (ETrailingSpaceRemoverException) выводим в чистом виде, необработанные предваряем сообщением о произошедшей ошибке, выводим класс исключения.

Скачать исходный код программы: Trailing Space Remover v.1.0 source code

Скачать исполняемый файл: Trailing Space Remover v.1.0 binary

 
 

25.04.2007

 
     
Hosted by uCoz