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
|