Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
6-1236235577
DrZloDey
2009-03-05 09:46
2011.04.10
Перенаправление портов


2-1294720735
DROWSY
2011-01-11 07:38
2011.04.10
Как в ячейке грида выводить текст, если значение поля


2-1294643049
Mitroshin
2011-01-10 10:04
2011.04.10
Как включить в FastReport показ миниатюр по умолчанию?


2-1293704422
Неважно
2010-12-30 13:20
2011.04.10
Цвет TBitmap


1-1252240815
atruhin
2009-09-06 16:40
2011.04.10
Delphi 2009/2010 string какой стандарт unicode?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский