Question

Copy a file

Asked by: dudup

Hi,

I need a good function to copy a file. It should be able to replace existing file, even if the file is the same.

I know the "CopyFile()" function, but it does not work as I expected.

I got error 18 (no more file) if I copy several files which already exists.

So, anyone has a good copy file function with error checking as well?

Thanks.

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2009-01-03 at 07:50:25ID24022498
Topic

Delphi Programming

Participating Experts
4
Points
250
Comments
11

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. CopyFile in VC++
    Hi, Could someone tell please tell me if there is any way of using CopyFile (or is there a similar funciton) that I can use to copy files with "*.ini" (*.*, etc)? i.e. copyfile("c:\\temp\\*.ini","d:\\dest"); or, will I have to write a function ...
  2. ProgressBar with copyfile
    I want to use a progressbar with the copyfile function. I want to let users know the progress of copying a file. How would I do this?
  3. Using Copyfile to print
    I want my c program to print an output text file automatically. I am using Copyfile to do this and in a test program it runs fine, but in my regular program I get the following error: "The file exist." Here is my code in both programs: if(!(CopyFile(Filename, Pri...
  4. Copy File Utility... How to use 'copyfile'
    Can anyone help me with my problem on how to copy a file, not using Shell("copy ...."). I need to use some Visual Basic 6.0 code to do this transaction. There is a command like 'copyfile'. How do I use it. Please provide sample code... Thanks... LeeKhim...
  5. CopyFile access denied
    I'm writting a File Manager program in MASM assembler. Everthing is looking fairly good, I have a tree view and two list views and a toolbar with the volume icons. I can change the display to a tree view and one list view or just two list views. The problem is I would like ...
  6. CopyFile
    I am trying to just copy a file. Can someone give me a good example of this?? Thanks

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: rionrocPosted on 2009-01-03 at 08:05:46ID: 23285725

Hello


var
  fileSource, fileDest: string;
begin
  fileSource := 'C:\SourceFile.txt';
  fileDest := 'G:\DestFile.txt';
  CopyFile(PChar(fileSource), PChar(fileDest), FALSE);
end;

{
  If this parameter is TRUE and the new file already exists, the function fails.
  If this parameter is FALSE and the new file already exists,
  the function overwrites the existing file and succeeds.
}

OR
you can do it by blockread and blockwrite, but the code maybe to long and must have an error trapping.


:)
rionroc

 

by: ahalyaPosted on 2009-01-03 at 08:11:13ID: 23285748

Copyfile will overwrite existing files if BFailifExists is false.  I don't see why it would matter whether you are copying one file, or several files. .

II have used the function below to recursively copy files without troubles.

procedure TForm1.DoCopyFiles(SourceDir, DestDir:string);
 
var
    Source, s: string;
    Result   : integer;
    SearchRec: TSearchRec;
    FailIfExists : boolean;
    Attr : Word;
 
begin;
if SourceDir[length(SourceDir)] <> '\' then SourceDir := SourceDir + '\';
if DestDir[length(DestDir)] <> '\' then DestDir := DestDir + '\';
Source := SourceDir + '*.*';
 
//copy all matching files first.
Result := FindFirst(Source, faAnyFile and (not faDirectory), SearchRec);
While Result = 0 do
  begin
  s := DestDir + SearchRec.Name;
  if not DirectoryExists(DestDir) then
     ForceDirectories(DestDir);
  FailIfExists := false;  //(RadioGroup1.ItemIndex <> 0);
  if not CopyFile(pchar(SourceDir+SearchRec.Name), pchar(s), FailIfExists) then
     begin;
        Memo1.Lines.Add('....' + SourceDir+SearchRec.Name + ' Error Copying File' + SysErrorMessage(GetLastError))
     end
  else   Memo1.Lines.Add(SourceDir+SearchRec.Name + ' copied');
  Result := FindNext(SearchRec);
  application.processmessages;
  end;
FindClose(SearchRec);
 
 
//recurse sub directories if necessary now.
if CheckBox1.Checked then
   begin;
   Result := FindFirst(Source, faDirectory, SearchRec);
   while Result = 0 do
       begin;
       if (SearchRec.Attr and faDirectory = faDirectory) and
          (SearchRec.Name <> '.') and
          (SearchRec.Name <> '..') then
          DoCopyFiles(SourceDir + SearchRec.Name, DestDir+SearchRec.Name);
       result := FindNext(SearchRec);
       application.processmessages;
       end;
   FindClose(SearchRec);
   end;
StatusBar1.SimpleText := 'done.';
end;
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:

Select allOpen in new window

 

by: dudupPosted on 2009-01-03 at 10:44:05ID: 23286417

I have more or less the same code (see attached).

It works if the destination folder is empty.

If I run for the second time, GetLastError() will return "18" (NO_MORE_FILES).

function  FixFolderName(f: string): string;
begin
  if Trim(f) <> '' then
    if f[Length(f)] <> '\' then f := f + '\';
  Result := Trim(f);
end;
 
function  CopyFolder(SrcFolder, DstFolder : String) : Boolean;
var
  SearchRec : TSearchRec;
  Src, Dst     : String;
 
begin
  Src := FixFolderName(SrcFolder);
  Dst := FixFolderName(DstFolder);
 
  if Not DirectoryExists(Dst) then ForceDirectories(Dst);
 
  Result := TRUE;
 
  if FindFirst(Src + '*.*', faAnyFile, SearchRec) = 0 then
    try
      repeat
        with SearchRec do
          if (Name <> '.') and (Name <> '..') then
            if (Attr and faDirectory) > 0 then
              Result := CopyFolder(Src + Name, Dst + Name)
            else
              Result := CopyFile(PChar(Src + Name), PChar(Dst + Name), FALSE); 
      until (FindNext(SearchRec) <> 0) or (not result);
    finally
      FindClose(SearchRec);
    end;
end;

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:

Select allOpen in new window

 

by: ahalyaPosted on 2009-01-03 at 11:00:00ID: 23286493

I would think "No More files" is not caused by  CopyFile, but by your FindNext.  If you call GetLastError is after the until statement then your code does not return the error from CopyFile. but from the findNext function.

Why don't you test return result of copyFile,
  if not CopyFile(pchar(SourceDir+SearchRec.Name), pchar(s), FailIfExists) then
     ShowMessage(SysErrorMessage(GetLastError))

or save the GetLastError before the until statement as below.

repeat
  with SearchRec do
    if (Name <> '.') and (Name <> '..') then
      if (Attr and faDirectory) > 0 then
        Result := CopyFolder(Src + Name, Dst + Name)
      else
        Result := CopyFile(PChar(Src + Name), PChar(Dst + Name), FALSE); 
     CopyError := GetLastError; //<----Extra Line Here..
until (FindNext(SearchRec) <> 0) or (not result);
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:

Select allOpen in new window

 

by: ahalyaPosted on 2009-01-03 at 11:00:56ID: 23286502

or simply switching the order of the logical operation might work as well.

until (not result) or (FindNext(SearchRec) <> 0);

                                              
1:

Select allOpen in new window

 

by: dudupPosted on 2009-01-03 at 11:09:29ID: 23286531

If I changed to this:

until (not result) or (FindNext(SearchRec) <> 0);

I got error 5 "Access Denied"

If I comment out the copyfile:

if (Attr and faDirectory) > 0 then
        Result := CopyFolder(Src + Name, Dst + Name)
      else;

I got no error ....

If I change the function to procedure like below, I got no error ...

Strange ...

I want to be able to exit immediately whenever there is an error, so I will use it like this:

if Not CopyFolder(.......) then e := GetLastError;    

procedure CopyFolder(SrcFolder, DstFolder : String);
var
  SearchRec : TSearchRec;
  Src, Dst     : String;
 
begin
  Src := FixFolderName(SrcFolder);
  Dst := FixFolderName(DstFolder);
 
  if Not DirectoryExists(Dst) then ForceDirectories(Dst);
 
  if FindFirst(Src + '*.*', faAnyFile, SearchRec) = 0 then
  begin
    try
      repeat
        //ShowError(Src+SearchRec.Name+'  @@@@  '+Dst+SearchRec.Name);
        with SearchRec do
          if (Name <> '.') and (Name <> '..') then
            if (Attr and faDirectory) > 0 then
              CopyFolder(Src + Name, Dst + Name)
            else
              CopyFile(PChar(Src + Name), PChar(Dst + Name), FALSE); // FALSE = Always overwrite
      until FindNext(SearchRec) <> 0;
    finally
      FindClose(SearchRec);
    end;
  end;
end;

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:

Select allOpen in new window

 

by: dudupPosted on 2009-01-03 at 11:26:40ID: 23286592

Hmm, I think you are right ... When I capture the CopyFile GetLastError, it was "Access Denied".

And I found that the existing folders are READ ONLY ...

But I dont know why this happen, because I deleted everything inside the destination folder ....

Then do the copy .... all the files inside the destination folder are now set to read only.

Is there any code to recursively unset the read only attribute?

 

by: ahalyaPosted on 2009-01-03 at 13:09:37ID: 23287029

Delphi has a FileSetAttr function, if I recall correctly.  You pass the filename, and the attributes.

You can use it prior to copying the files, I suppose.

 

by: swiatloPosted on 2009-01-09 at 02:50:12ID: 23334311

Maybe this is a good method:

Check if dest file existes (FileExists), If it does, then delete it (DeleteFile)
Use (RenameFile) to copy. If you want to preserve org source file you would have to store it in temp folder, and then put it back after renamed/move has succeed.

 

by: rllibbyPosted on 2009-01-14 at 10:50:27ID: 23376001

You could just use the same routine that the OS does...

Regards,
Russell

--- example ---

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ShellApi, StdCtrls, FileCtrl;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation
{$R *.DFM}

function CopyFiles(SourceFolder, DestFolder: String): Boolean;
var  lpFileOp:      TSHFileOpStruct;
     szSource:      String;
     szDest:        String;
begin

  // Force dest directory
  if not(DirectoryExists(DestFolder)) then ForceDirectories(DestFolder);

  // Clear structure
  FillChar(lpFileOp, SizeOf(lpFileOp), 0);

  // Get source and dest locations
  szSource:=IncludeTrailingBackslash(SourceFolder) + '*' + #0#0;
  szDest:=ExcludeTrailingbackslash(DestFolder) + #0#0;

  // Set structure fields
  lpFileOp.Wnd:=Application.Handle;
  lpFileOp.wFunc:=FO_COPY;
  lpFileOp.pFrom:=Pointer(szSource);
  lpFileOp.pTo:=Pointer(szDest);
  lpFileOp.fFlags:=FOF_NOCONFIRMATION or FOF_NOERRORUI or FOF_NOCONFIRMMKDIR or FOF_SILENT;

  // Execute the file operation
  result:=(SHFileOperation(lpFileOp) = 0) and not(lpFileOp.fAnyOperationsAborted);

end;

procedure TForm1.Button1Click(Sender: TObject);
begin

  if CopyFiles('c:\temp',  'c:\temp1') then
     ShowMessage('Success')
  else
     ShowMessage('Failure');
     
end;

 

by: dudupPosted on 2009-02-24 at 02:08:46ID: 23719844

ahalya,

you are right, I need to change the file attribute to archive if copy fail :)

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...