Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

[Delphi 2006, Access] Загрузка файла в базу данных [Access MDB]


Дмитрий ©   (2009-02-20 08:55:00) 

Добрый день.

Такая проблема: загружаю файл в базу данных, необходимо отслеживать ход выполнения, поэтому пишу кусками, работа с потоками выглядит так:

Function CopyData(Source, Destination: TStream; Count: Int64): Int64;
  Function Min(a: Int64; b: Integer): Integer;
  Begin
       if (a<0) or (b<a) then result:=b else result:=a;
  End;
Var
  BSize: Integer;
  B: PChar;
  BytesToRead,BytesRead: Integer;
  Block : integer;
  i : integer;
Begin
  i:=0;
  FPB.Properties.Min := 0;
  block := Count div $F000;
  FPB.Properties.Max := (block div 10) + 1;
  Result:=0;
  BSize:=Min(Count,$F000);
  GetMem(B, BSize);
  try
     repeat
        BytesToRead:=Min(Count,BSize);
        BytesRead:=Source.Read(B^,BytesToRead);
        Destination.Write(B^,BytesRead);
        Inc(Result,BytesRead); Dec(Count,BytesRead);
        inc(i);
        if i mod 10 = 0 then FPB.Position := i/10;
        Application.ProcessMessages;
     until (BRead<BytesToRead) or (Count=0);
   finally
     FreeMem(B, BSize);
   end;
End;

В основе - код, найденный на просторах рунета.
Процесс загрузки постепенно замедляется и с резвого бега в начале переходит к вялому ползанию в конце. Можно это как-то исправить, от чего оно зависит?
Кроме того, последующий вызов метода Post занимает практически столько же времени, а отобразить его бегунком уже нельзя. Может, я в принципе использую неправильный подход и надо сделать все по-другому? Тогда как?


Сергей М.   (2009-02-22 17:55:00) [1]

function TMyFileStream.Read(var Buffer; Count: Longint): Longint; //override
begin
  Result := inherited Read(Buffer, Min(Count, BSize)); // вуаля !!
end;


Сергей М.   (2009-02-22 17:47:00) [2]


> необходимо отслеживать ход выполнения


Существует изящный способ реализации подобных задач - использование своего наследника TFileStream с перекрытым методом Read.


Сергей М.   (2009-02-22 17:31:00) [3]


> Дмитрий


aqBase - это кто, ADOQuery ?

А зачем же делать селективный запрос и возвращать навигируемый НД (подозреваю что CursorLocation у него = clUseClient, т.е. сразу в лес с мылом и веревкой), если все что требуется от метода TFDM.AddFile - это добавитьзапись ?


Amoeba   (2009-02-20 16:59:00) [4]


> Дмитрий   (20.02.09 12:00) [4]

А кто за тебя будет вызывать Free  у blob и fs? Пушкин? Да здравствуют утечки памяти?


Sergey13   (2009-02-20 13:38:00) [5]

> [6] Дмитрий   (20.02.09 12:28)
> Там будут создаваться новые базы при исчерпании лимита.

Кошмар! Потом будешь делать отдельную БД для навигации по заполненным? Это ТЗ тоже такое?


Дмитрий   (2009-02-20 12:28:00) [6]

Там будут создаваться новые базы при исчерпании лимита. Вообще, большие файлы - редкость, но могут быть, может, один на базу.


Sergey13   (2009-02-20 12:01:00) [7]

> [2] Дмитрий   (20.02.09 11:12)
> а когда под сотню

И кстати, а сколько таких файлов ты собираешься записать? У аксеса вроде ограничение на размер файла вроде есть 2 гига. Хотя могу и ошибаться, но что то тут про это говорили.
Например тут
http://www.delphimaster.ru/cgi-bin/forum.pl?n=1&id=1235022074


Дмитрий   (2009-02-20 12:00:00) [8]

На ТЗ тоже забить?

Есть еще одна проблема. На методе Post прога начинает сильно отжирать память, на 50 метровый файл 500 оперативки. Там явно что-то не то, но что может быть?

Код еще одной функции:

function TFDM.AddFile(const Path : string): integer;
var
 blob: TStream;
 fs : TFileStream;
 sMsg : string;
begin
 with aqBase do begin
   SQL.Text := 'select * from FTABLE where ID = 0';
   Active := true;
   Append;

   blob := CreateBlobStream(FieldByName('FILE'), bmWrite);
   fs := TFileStream.Create(Path, fmOpenRead);
   sMsg := CopytoField (fs, blob);// там вызывается CopyData
   if sMsg <> '' then MessageBox (0, PChar(sMsg), 'Ошибка', MB_OK + MB_ICONERROR);
   FieldByName('NAME').AsString := ExtractFileName(Path);
   Post;
   result := FieldByName('ID').AsInteger;
   Active := False;
 end;  //  with
end;


Sergey13   (2009-02-20 11:37:00) [9]

> [2] Дмитрий   (20.02.09 11:12)

ИМХО все исключительно.
Делать такое нужно тогда, когда пользователь должен по ходу процесса принимать решения по его продолжению/отмене, направлять процесс изменяя какие то параметры. Я так понимаю, что ничего такого у тебя не предполагается. Это все равно что предлагать гонщикам Ф1 во время гонки выходить из машины на каждом круге и отмечаться в ведомости, что бы узнать кто за кем едет.

Повесь анимашку для развлечения юзера и забей на это.


Дмитрий   (2009-02-20 11:12:00) [10]

Когда файлик на пару мегобайт - смысла нет, а когда под сотню, то процесс занимает уже продолжительное время и показывать пользователю висячее окно не гоже.


Sergey13   (2009-02-20 09:32:00) [11]

> [0] Дмитрий   (20.02.09 08:55)
> необходимо отслеживать ход выполнения

А смысл?


Наверх

Титульная страница Поиск, карта сайта Написать письмо