Форум: "Начинающим";
Текущий архив: 2011.04.10;
Скачать: [xml.tar.bz2];
Внизпосоветуйте, как организовать алгоритм Найти похожие ветки
← →
пишу_курсовой (2011-01-12 15:53) [0]приложение, в определенные моменты извлекает из архивов (.zip) файлы и выполняет определенные действия с ними. В ТЗ сказано, если не удалось извлеч файл, райсить эксепшен - "Не удалось извлечь файл "<имя_файла_в_пакете_обновления>" из пакета обновления" "<имя_файла_пакета_обновления>". Вопрос: Как более гибко и оптимально организовать алгоритм извлечения.
1. Написать отдельную процедуру, возвращающую в качестве out-параметра TStream (извлекаемый файл)
procedure pack_file_get(APack: TZipFoge; const Afile_name: string;
out AStream);
begin
AStream := TMemoryStream.Create;
try
APack.ExtractToStream(AStream);
except
raise Exception.CreateFmt(C_CANNOT_LOAD_FILE,
[Afile_name, APack.FileName]);
AStream.Free;
end;
end;
2. Обойтись без процедуры, и напряму в коде создавать TStream, извлекать в него и обрабатывать try..except
3. Как бы сделали вы?
← →
Сергей М. © (2011-01-12 16:07) [1]Отдельная процера нужна в случае многократного использования одного и того же алгоритма. А это как раз твой случай, поскольку кол-во файлов в архиве заранее неизвестно, что предполагает услловно-циклическое обращение к алгоритму извлечения файла.
Другой вопрос что при массированном извлечении, вожможно, есть резон вынести создание объекта-стрима в вызывающий код.
← →
пишу_курсовой (2011-01-12 16:12) [2]
> есть резон вынести создание объекта-стрима в вызывающий
> код.
т.е. параметр AStream сделать как var?
← →
Сергей М. © (2011-01-12 16:16) [3]Вот как раз не var и не out.
var и out нужны когда объект-результат создается в вызываемом коде, т.е. именно как у тебя проиллюстрировано в п.1
← →
пишу_курсовой (2011-01-12 16:23) [4]как тогда передать в вызываемый код объект-стрим, создаваемый в вызывающем коде, не используя var, в инете видел много примеров такой организаций только с использованием var
← →
Сергей М. © (2011-01-12 16:31) [5]
> как тогда передать в вызываемый код объект
Для этого нужно совсем малое - понимание того факта что дельфийские данные объектного типа есть суть указатели. Передавая факт.параметром значение переменной ms: TStream ты по сути передаешь указатель на местоположение в памяти конкретного объекта класса TStream. Нет никакой нужды передавать указатель на указатель, помечая форм.параметр как var или out.
← →
пишу_курсовой (2011-01-12 16:37) [6]вот я ступил!!!, спасибо
← →
пишу_курсовой (2011-01-12 16:42) [7]забыл спросить, на интерфейсы такая же логика распространяется? к примеру у меня есть некий интерфейс IMyInterface который я передаю в процедуру/функцию и чтот-то делаю. объявление как var будет лишним?
← →
Ega23 © (2011-01-12 16:45) [8]
> как var будет лишним?
да
← →
Сергей М. © (2011-01-12 16:48) [9]да
объект, представленный интерфейсом, - это тоже ссылка.
← →
Юрий Зотов © (2011-01-12 16:59) [10]
except
raise Exception.CreateFmt(C_CANNOT_LOAD_FILE, [Afile_name, Pack.FileName]);
AStream.Free; // Эта строка никогда не выполнится.
end;
Поменяйте местами.
← →
пишу_курсовой (2011-01-12 17:02) [11]спс. не заметил, AStream.Free вообщем-то уже не нужен, раз объект стрим создается вне.
← →
Юрий Зотов © (2011-01-12 17:18) [12]
> 1. Написать отдельную процедуру, возвращающую в качестве
> out-параметра TStream (извлекаемый файл)
Отдельная процедура - это правильно. Но чтобы сама она создавала объект и возвращала его - это не очень хороший стиль (чреват утечками памяти). Правильнее создавать и уничтожать объект в рамках одной и той же процедуры, причем в блоке try-finally:procedure pack_file_get(APack: TZipFoge; Afile_name: string; AStream: TMemoryStream);
begin
try
APack.ExtractToStream(AStream);
except
raise Exception.CreateFmt(C_CANNOT_LOAD_FILE, [Afile_name, APack.FileName]);
end;
end;
Вызов такой:procedure MyProc(APack: TZipFoge; Afile_name: string);
var
AStream: TMemoryStream;
begin
AStream := TMemoryStream.Create;
try
pack_file_get(APack, Afile_name, AStream);
... // Работаем с потоком AStream
finally
AStream.Free;
end;
end;
Причем используя вложенный блок (try-except внутри try-finally) эти две процедуры можно объединить в одну - и это, пожалуй, будет самое правильное решение.procedure MyProc(APack: TZipFoge; Afile_name: string);
var
AStream: TMemoryStream;
begin
AStream := TMemoryStream.Create;
try
try
APack.ExtractToStream(AStream);
except
raise Exception.CreateFmt(C_CANNOT_LOAD_FILE, [Afile_name, APack.FileName]);
end;
... // Работаем с потоком AStream
finally
AStream.Free;
end;
end;
← →
Юрий Зотов © (2011-01-12 17:31) [13]И, наверное, стоит показать текст сообщения о реально возникшей ошибке:
...
try
APack.ExtractToStream(AStream);
except
on E: Exceprtion do
raise Exception.CreateFmt(..., [Afile_name, APack.FileName, E.Message]);
end;
...
Иначе истинная причина ошибки окажется "спрятанной".
← →
пишу_курсовой (2011-01-12 17:35) [14]
> Причем используя вложенный блок (try-except внутри try-finally)
> эти две процедуры можно объединить в одну - и это, пожалуй,
> будет самое правильное решение.
>
> procedure MyProc(APack: TZipFoge; Afile_name: string);
> var
> AStream: TMemoryStream;
> begin
> AStream := TMemoryStream.Create;
> try
> try
> APack.ExtractToStream(AStream);
> except
> raise Exception.CreateFmt(C_CANNOT_LOAD_FILE, [Afile_name,
> APack.FileName]);
> end;
> ... // Работаем с потоком AStream
> finally
> AStream.Free;
> end;
> end;
этот вариант отпадает, должна быть возможность возвращать Stream. На различных этапах (отдельные процедуры) после извлечения будут выполнятся различные действия (определенные типы файлов имеют определенное функциональное назначение), где-то нужно получить размер извлеченного файла, где-то его контрольную сумму, где-то стрим будет разбиваться на отдельные куски которые будут записываться в другой стрим
← →
Юрий Зотов © (2011-01-12 17:46) [15]
> На различных этапах (отдельные процедуры) после извлечения
> будут выполнятся различные действия (определенные типы файлов
> имеют определенное функциональное назначение), где-то нужно
> получить размер извлеченного файла, где-то его контрольную
> сумму, где-то стрим будет разбиваться на отдельные куски
> которые будут записываться в другой стрим
Вот для всего этого и написано:... // Работаем с потоком AStream
Возможно, есть смысл породить потомка TZipFoge и добавить в него public свойство Stream - тогда к этому свойству можно будет обращаться везде. Соответственно, в конструкторе этот Stream надо создать, а в деструкторе - уничтожить. Также нужно будет написать метод записи в этот Stream, а в нем перед вызовом ExtractToStream вызывать Clear.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.04.10;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.005 c