Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to copy a file during Runtime? 2

Status
Not open for further replies.

delphiman

Programmer
Dec 13, 2001
422
ZA
I am using the following code which successfully copies a file from one
Folder to another. But the file gets corruped in the process.
In that the Active Property of the TTable component becomes False and if I try to make it True I get exception "Corrupt table/index header."

Also ...if I try and examine the copied file with Delphi Desktop I get a "Cannot open file" exception.

I might add I have tried including MyFile.px, by duplicating the routine below for that file - with the same result.

Any suggestions ....? Anyone??


procedure TfrmMyForem.btnCopyFileClick(Sender: TObject);
var
FileName, DestName: string;
CopyBuffer: Pointer; { buffer for copying }
BytesCopied: Longint;
Source, Dest: Integer; { handles }
Len: Integer;
Destination: TFileName; { holder for expanded destination name }
begin
DestName := ('c:\SecondFolder\MyFile.db');
Destination := ExpandFileName(DestName); { expand the destination path }
if HasAttr(Destination, faDirectory) then { if destination is a directory... }
begin
Len := Length(Destination);
FileName := ('c:\FirstFolder\MyFile.db');
if Destination[Len] = '\' then
Destination := Destination + ExtractFileName(FileName) { ...clone file name }
else
Destination := Destination + '\' + ExtractFileName(FileName); { ...clone file name }
end;
GetMem(CopyBuffer, ChunkSize); { allocate the buffer }
try
Source := FileOpen(FileName, fmShareDenyWrite); { open source file }
try
Dest := FileCreate(Destination); { create output file; overwrite existing }
try
repeat
BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize); { read chunk }
if BytesCopied > 0 then { if we read anything... }
FileWrite(Dest, CopyBuffer^, BytesCopied); { ...write chunk }
until BytesCopied < ChunkSize; { until we run out of chunks }
finally
FileClose(Dest); { close the destination file }
end;
finally
FileClose(Source); { close the source file }
end;
finally
FreeMem(CopyBuffer, ChunkSize); { free the buffer }
end;
end;
 
Have you tried using the debugger to find out the problem with this code?

What size is the created MyFile.db file in the SecondFolder? When I ran your code, the variable FileName was never assigned a value and hence the source file did not get opened.

Where is the function HasAttr defined?

What is the value of ChunkSize?


I tend to use simpler code when copying files - along the lines of:
Code:
procedure CopyFile ( const source, destination: string );
begin
  with TMemoryStream.Create do try
    LoadFromFile ( source );
    SaveToFile ( destination );
  finally
    Free;
  end;
end;

Andrew
 
Thanks Andrew!

Your simplified code looks more like what I wanted in the first place.

But you appear to have missed the fact that I use a button to activate what I want.

I tried the following ...

procedure CopyFile ( const source, destination: string );
begin
with TMemoryStream.Create do try
LoadFromFile ('c:\FirstFolder\MyFile.db');
SaveToFile ('c:\SecondFolder\MyFile.db');
finally
Free;
end;
end;


And I get the (remarked) exceptions if I try the following

procedure TfrmMyForm.btnCopyFileClick(Sender: TObject);
begin
CopyFile; //Exception &quot;Not enough parameters&quot;
OR
CopyFile ( const source, destination: string ); // Exception Expression expected. Const found&quot;
end;

What am I missing ..? :)
 
I provided a simple general purpose routine for copying files. Note that there is no error handling to cope with missing files. So you should put some checks in for the existance of the source and destinations paths and files.

You would need to call CopyFile from your button's OnClick event handler:
Code:
procedure CopyFile ( const source, destination: string );
begin
  with TMemoryStream.Create do try
    LoadFromFile ( source );
    SaveToFile ( destination );
  finally
    Free;
  end;
end;
...
procedure TfrmMyForem.btnCopyFileClick(Sender: TObject);
begin
  CopyFile('c:\FirstFolder\MyFile.db','c:\SecondFolder\MyFile.db'); 
end;
In practice, if you are copying Paradox databases, your code would should copy all the files associated with that database, not just the .db file.

Andrew
 
Huston .... we have a problem!!

you should put some checks in for the existance of the source and destinations paths and files.
For the moment I have insured that 'c:\FirstFolder\MyFile.db'[/color] is in place without 'MyFile.db'[/color] being in
place in 'c:\SecondFolder\'[/color] as well as with it being in place.

From a BreakPoint being placed on LoadFromFile
I am able to establish that source and
destination reflects the following in them respectively
'c:\FirstFolder\MyFile.db' and ,'c:\SecondFolder\MyFile.db'

But the moment I advance the BreakPoint off LoadFromFile with F8 I get exception ...
Cannot open file c:\FirstFolder\MyFile.db'.

your code would should copy all the files associated with that database, not just the .db file.

The only other file would be 'c:\FirstFolder\MyFile.px' being the Index File.
I was going to handle that once I got the above to work ... but now it appears they perhaps they have to copied together
which begs the question &quot;How? I have tried copying MyFile.px first but
get the same exception.
 
Huston ....! Problem parially solved! :)

I have just realised that my problem must relate to the fact that MyFile.db is Active and in use. Because I tried other files (totally unrelated to my project) and they copied perfectly.

I then tried ...

with TMemoryStream.Create do try
QryMyFile.Active := False;
LoadFromFile ( source );
SaveToFile ( destination );
finally
Free;
end;

..... which does not solve my problem. I really would like
to copy the file without coming completely out of the program. :-(

Any ideas ..??
 
It would not be a good idea to copy the files if the MyFile table was in use. It shouldn't be necessary to come out of the program. Just make sure that the file is not being used by anything. I.e. the table muse be closed.

If you are running the program within the Borland IDE it might be worth checking that the Active property is set to false in the TTable component for your MyFile table.

If you still have a problem, post your code to this thread.

Andrew

 
it might be worth checking that the Active property is set to false in the TTable component for your MyFile table.

The only connection to the MyFile.db is via the TQuery component mentioned above. And (as you can see) I tried making Active := False for the event. But I still get the exception.

 
Do you have DBExplorer open in the IDE?

What happens if you run the program outside of the IDE?

Can you post the actual code you use to copy the file?


Andrew
 
>Do you have DBExplorer open in the IDE?
No.


>Can you post the actual code you use to copy the file?

>What happens if you run the program outside of the IDE?
Can't try now - but I sha;; and get back to you.

Code is like this and if I run it out of a totally new (isolated) Project it works fine.

procedure CopyFile ( const source, destination: string );
begin
with TMemoryStream.Create do try
LoadFromFile ( source );
SaveToFile ( destination );
finally
Free;
end;
end;

procedure TfrmRegisterAll.btnCopyForUDClick(Sender: TObject);
begin
CopyFile('c:\Folder1\MyFile.db','c:\Folder2\MyFile.db');
end;

 
So it works the first time you run the program and the second (and subsequent) time it fails with a 'Cannot Open File' exception ?

When you say a &quot;totally new (isolated) project&quot;, what do you mean? Are Folder1 and Folder2 new as well?

Whereabouts are you checking that MyFile.db exists?

Any luck with running it outside of the IDE?

Andrew
 
>So it works the first time you run the program and the >second (and subsequent) time it fails with a 'Cannot Open >File' exception ?

Negative. It won't work at all. I get the exception.

>When you say a &quot;totally new (isolated) project&quot;, what do >you mean?

I came out of the project where I am trying to do use the code. Created a simple project - with just a button and the code you gave me. No components connected to it - NOTHING -and it works perfectly. So clearly the code won't tolerate a component being hooked to it. I have even tried making Active := False along with MyTable := Closed.


>Whereabouts are you checking that MyFile.db exists?
At his stage I am not even. I shall get to that later. Firstly I want a rooutine that works under optimum conditions. So I am simply making sure that there is NOTHING in the target folder. (Also tried with the same file IN the target folder (am trying to COPY after all). Same exception.

>Any luck with running it outside of the IDE?
Negative. Same exception.
 
Have you tried completely unloading the table and then copying? That should work.

Hope this helps,

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
 
>Have you tried completely unloading the table and then copying?

&quot;unloading&quot;??
Don't understand. :)
 
Are there any other programs either on your computer or on a networked computer accessing MyFile.db ?

It would be useful to put an Assert statement in the CopyFile procedure to help debugging:
Code:
procedure CopyFile ( const source, destination: string );
begin
  Assert ( FileExists(source) );
  with TMemoryStream.Create do try
    LoadFromFile ( source );
    SaveToFile ( destination );
  finally
    Free;
  end;
end;

Andrew
 
We'll you have the table you want to copy in the memory right? Windows wont let you copy unless its completely unused. So you cant have it in the memory of anything. Not in your programs or in any other.

[bobafett] BobbaFet [bobafett]

Everyone has a right to my opinion.
E-mail me at caswegkamp@hotmail.com
 
towerbase and BobbaFet you are both a great credit to this website. Thanks!

towerbase &quot;Assert&quot; is a new one on me and very interesting.

BobbaFet
Windows won't let you copy unless its completely unused.
I guess that makes sense and confirms why, when I do as outlined on 15th Sept (above,) that works.

So to overcome my problem I now run a completely seperate program without referencing the relevant database by means of any component of any description. To this end I have adapted what can be found at c:\Program Files\Borland\Delphi6\Demos\Doc\Filmanex .
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top