Loading a file

jrydberg
jrydberg used Ask the Experts™
on
I want to know how to use a progress bar while loading. I've done like this now:

I have a TStatusBar on the form, a TProgressBar (on the status bar), and a TMemo. I'm using a VERY SLOW code for loading a file into the TMemo:

procedure TForm1.LoadFile(FileName: String);
var
  FS: TFileStream;
  Buffer: Char;
begin
  FS := TFileStream.Create(FileName);
  try
    ProgressBar1.Max := FS.Size;
    ProgressBar1.Position := 0;
    while FS.Position < FS.Size do
    begin
      FS.Read(Buffer, SizeOf(Buffer));
      Memo1.Text := Memo1.Text + Buffer;
      ProgressBar1.Position := FS.Position;
    end;
  finally
    FS.Free;
    ProgressBar1.Position := 0;
  end;
end;

The problem is that it is so slow. I've tried setting the Buffer variable to an array of characters, but then, it doesn't read the all of the contents in the file.

Any ideas?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2004

Commented:
? why not use

memo1.lines.loadfromfile('Filename');
//is then there a progressbar needed?

meikl ;-)

Commented:
or load the file into a stringlist
then in a for loop ( for sl.count down to 0 ) copy the stringlist line by line into memo and update progressbar (progressbar.positin := memo1.lines.count )
or similar..
Hi,

It's slow because you are reading the file char by char. If you increase the size of the buffer then the process will be faster. Try this code:

procedure TForm1.LoadFile(FileName: String);
var
 FS: TFileStream;
 Buffer: array [1..100] of Char; // change the size of the buffer to see how it will work - [1..1] is your case now
 BytesRead, TotalBytes: longint;
begin
 TotalBytes := 0;
 FS := TFileStream.Create(FileName,fmOpenRead);
 try
   ProgressBar1.Max := FS.Size;
   ProgressBar1.Position := 0;
   while true do
   begin
     BytesRead := FS.Read(Buffer, SizeOf(Buffer));
     TotalBytes := TotalBytes + BytesRead;
     Memo1.Text := Memo1.Text + Copy(string(Buffer),1,BytesRead);
     if TotalBytes = FS.Size then break;
     ProgressBar1.Position := FS.Position;
   end;
 finally
   FS.Free;
   ProgressBar1.Position := 0;
 end;
end;

Regards, Geo
Fundamentals of JavaScript

Learn the fundamentals of the popular programming language JavaScript so that you can explore the realm of web development.

Commented:
Hi, in order to make ProgressBar updated during heavy tasks like loading. Just put
Application.ProcessMessages
after each
ProgressBar1.Position := FS.Position;

regards,
Monir


 
In that particular case don't use Application.ProcessMessages. First, you don't need to because the ProgressBar does get refreshed, and second, your CPU will go up to 100 percent usage.

Regards, Geo

Author

Commented:
Thanks, Geo! That was just what I was looking for. But now, I have another problem. How should I do to show the progress bar while saving a file? I'm only writing char by char right now, is there any easy way to write multiple chars at ones?
Top Expert 2004

Commented:
? only the sense i'm missing

Line by line from a memo:

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin
  ProgressBar1.Max := Memo1.Lines.Count;
  ProgressBar1.Position := 0;
  with TFileStream.Create('c:\test.txt', fmCreate or fmShareCompat) do try
    for i := 0 to Memo1.Lines.Count - 1 do begin
      Write(PChar(Memo1.Lines[i])^, Length(Memo1.Lines[i]));
      Write(#13#10,2);
      ProgressBar1.Position := ProgressBar1.Position + 1;
    end;
  finally
    Free;
    ProgressBar1.Position := 0;
  end;
end;

Regards, Geo

Commented:
Hi, in order to make ProgressBar updated during heavy tasks like loading. Just put
Application.ProcessMessages
after each
ProgressBar1.Position := FS.Position;

regards,
Monir


 

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial