Board index » cppbuilder » copy files and directorys on recursiv way - directory folder problem

copy files and directorys on recursiv way - directory folder problem


2004-07-02 07:07:34 AM
cppbuilder16
Hi,
in my application i use a recursiv copy routine, to copy all files and
directorys from a to b. my problem is that my copy functions seems to try to
copy folders and write error messages.
my code works fine! every file will be copy! nothing is missing. but i
always get errors. For exmaple:
-----------------------------
C:\\Datenbank\c64 could not copy: Access denied
C:\\Games\c64 to C:\\Datenbank\c64 did not copy
-----------------------------
C:\\Datenbank\c64 is a directory and not a file. why is my application try
to copy this? i do not understand.
here are my recursive function and my copy function:
void __fastcall TForm1::dir_create(AnsiString source, AnsiString target)
{
TSearchRec sr;
source = IncludeTrailingBackslash(source);
AnsiString wildcard = source + "*";
target = IncludeTrailingBackslash(target);
// Attribute
int iAttributes = faDirectory;
if (FindFirst(wildcard,iAttributes, sr) == 0)
{
do
{
// Directory
if( (sr.Attr & faDirectory) && (sr.Name != ".") && (sr.Name !=
"..") )
{
if (!DirectoryExists(target + sr.Name))
{
CreateDir(target + sr.Name);
}
LStatus2->Caption = target + sr.Name;
Application->ProcessMessages();
dir_create(source + sr.Name, target + sr.Name);
}
// File
if( (sr.Attr & faAnyFile) && (sr.Name != ".") && (sr.Name !=
"..") )
{
LStatus2->Caption = target + sr.Name;
Application->ProcessMessages();
CopyTheFile(source + sr.Name,target + sr.Name);
}
}
while(FindNext(sr) == 0);
FindClose(sr);
}
FindClose(sr);
}
//--------------------------------------------------------------------------
-
bool __fastcall TForm1::CopyTheFile(String source, String target)
{
BOOL bCancelled = FALSE;
bool back = CopyFileEx(source.c_str(),
target.c_str(),MyCopyProgressRoutine, this, &bCancelled,
COPY_FILE_RESTARTABLE);
// Bei Fehlermeldung anzeigen
if (back == false)
{
DWORD er = GetLastError();
char er_str[200];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,er,0,(char*)&er_str,200,NULL);
MProtokoll->Lines->Add("-----------------------------");
MProtokoll->Lines->Add(target + " could not copy: " + er_str);
MProtokoll->Lines->Add(source + " to " + target + " did not copy");
MProtokoll->Lines->Add("-----------------------------");
// ShowMessage(er_str);
}
return back;
}
//--------------------------------------------------------------------------
-
Might there be any problems when some files are write protected and i try to
overwrite them?
any ideas for my problem?
tommy
 
 

Re:copy files and directorys on recursiv way - directory folder problem

"Tommy" < XXXX@XXXXX.COM >wrote in message
Quote
C:\\Datenbank\c64 is a directory and not a file.
why is my application try to copy this?
Because your code logic is flawed. You are allowing CopyTheFile() to be
called on directories.
Quote
here are my recursive function and my copy function:
Use this code instead:
void __fastcall TForm1::dir_create(AnsiString source, AnsiString target)
{
source = IncludeTrailingBackslash(source);
target = IncludeTrailingBackslash(target);
TSearchRec sr;
if( FindFirst(source + "*.*", faAnyFile, sr) == 0 )
{
do
{
if( (sr.Name == ".") || (sr.Name == "..") )
continue;
AnsiString CurrentSource = source + sr.Name;
AnsiString CurrentTarget = target + sr.Name;
LStatus2->Caption = CurrentTarget;
if( sr.Attr & faDirectory )
{
if( !DirectoryExists(CurrentTarget) )
CreateDir(CurrentTarget);
Application->ProcessMessages();
dir_create(CurrentSource, CurrentTarget);
}
else
{
Application->ProcessMessages();
CopyTheFile(CurrentSource, CurrentTarget);
}
}
while( FindNext(sr) == 0 );
FindClose(sr);
}
}
bool __fastcall TForm1::CopyTheFile(String source, String target)
{
BOOL bCancelled = FALSE;
bool bRet = CopyFileEx(source.c_str(), target.c_str(),
MyCopyProgressRoutine, this, &bCancelled, COPY_FILE_RESTARTABLE);
if( !bRet )
{
MProtokoll->Lines->Add("-----------------------------");
MProtokoll->Lines->Add(target + " could not copy: " +
SysErrorMessage(GetLastError()));
MProtokoll->Lines->Add(source + " to " + target + " did not
copy");
MProtokoll->Lines->Add("-----------------------------");
}
return bRet;
}
Gambit
 

Re:copy files and directorys on recursiv way - directory folder problem

hi remy,
thanks for your help. might you tell me, where was the error in my old
function?
perhabs you can also help me with my second problem.
in my application i like to copy completly directorys from a to b. while
copying i like to show the status how many percent of the actual copyied
file is finished and how many percent of all files are finished. all this
works fine!!!
my only problem is the calculation of the time with is still need till the
copy proccess is finished. and the time which is elapsed since starting my
process.
the elapsed time since starting my proccess has a little error. it starts
mith 2 hours. 2 hours seems to be the initual value. but it have to start at
0.
the time with my proccess will still need till the proccess is finished is
not good enought. the copy of my test directory takes 2 minutes. my
calculation says, that this need 18hours and reduces slowly to 0. After the
proccess is finished, the 0 was reached. what could i do, that the
calculation is more precise and does not start with 18h.
here is my source code:
in my header:
unsigned __int64 size;
unsigned __int64 tmp;
unsigned __int64 already_copied;
unsigned __int64 rest;
above my cpp file:
// global structure for time calcaulation
typedef union uFT264{
FILETIME ft;
DWORDLONG i64;
}FT264;
// global variables vor time calculation
FT264 StartTime;
FT264 now;
FT264 remaining;
FT264 elapsed;
// last value
FT264 last;
// My rekursiv function i modify a bit
void __fastcall TForm1::dir_create(AnsiString source, AnsiString target)
{
source = IncludeTrailingBackslash(source);
target = IncludeTrailingBackslash(target);
TSearchRec sr;
if( FindFirst(source + "*.*", faAnyFile, sr) == 0 )
{
do
{
if( (sr.Name == ".") || (sr.Name == "..") )
continue;
AnsiString CurrentSource = source + sr.Name;
AnsiString CurrentTarget = target + sr.Name;
LStatus2->Caption = CurrentTarget;
if( sr.Attr & faDirectory )
{
if( !DirectoryExists(CurrentTarget) )
CreateDir(CurrentTarget);
Application->ProcessMessages();
dir_create(CurrentSource, CurrentTarget);
}
else
{
Application->ProcessMessages();
// new file, thus filesize = 0
tmp = 0;
// overwrite file or not
if (RBOverwrite->Checked == false && FileExists(CurrentTarget))
{
// get file size
ULARGE_INTEGER ul;
ul.LowPart = sr.FindData.nFileSizeLow;
ul.HighPart = sr.FindData.nFileSizeHigh;
tmp = (unsigned __int64)ul.QuadPart;
// get new status of all files
CGauge2->Progress = ((unsigned
__int64)((already_copied+tmp)*100))/(unsigned __int64)(size);
}
else
{
// copy the file
if (CopyTheFile(CurrentSource, CurrentTarget) == false)
{
// if an error occured, get file size
ULARGE_INTEGER ul;
ul.LowPart = sr.FindData.nFileSizeLow;
ul.HighPart = sr.FindData.nFileSizeHigh;
tmp = (unsigned __int64)ul.QuadPart;
}
}
already_copied += tmp;
}
}
while( FindNext(sr) == 0 );
FindClose(sr);
}
}
// start copy process
void __fastcall TForm1::BStartClick(TObject *Sender)
{
already_copied = 0;
size = 0;
tmp = 0;
// get size of all bytes to copy. this works fine
size = GetFolderSize(ESource->Text);
GetSystemTimeAsFileTime(&StartTime.ft);
Application->ProcessMessages();
dir_create(ESource->Text,ETarget->Text);
}
AnsiString __fastcall TForm1::FormatTime(SYSTEMTIME *time)
{
String backtime = AnsiString(time->wHour) + AnsiString(":") +
AnsiString(time->wMinute) + AnsiString(":") + AnsiString(time->wSecond);
return backtime;
}
DWORD WINAPI MyCopyProgressRoutine(LARGE_INTEGER TotalFileSize,LARGE_INTEGER
TotalBytesTransferred,LARGE_INTEGER StreamSize,LARGE_INTEGER
StreamBytesTransferred,DWORD dwStreamNumber,DWORD dwCallbackReason,HANDLE
hSourceFile,HANDLE hDestinationFile,LPVOID lpData)
{
TForm1 *pForm = (TForm1*) lpData;
if (TotalFileSize.QuadPart>0)
{
// actual file status
unsigned __int64 Percent = (((unsigned
__int64)TotalBytesTransferred.QuadPart)*100) / ((unsigned
__int64)TotalFileSize.QuadPart);
pForm->CGauge1->Progress = Percent;
// status of all files
pForm->tmp = (unsigned __int64)TotalBytesTransferred.QuadPart;
Percent = ((unsigned
__int64)((pForm->already_copied+pForm->tmp)*100))/(unsigned
__int64)(pForm->size);
pForm->CGauge2->Progress = Percent;
}
// time calculation
now.i64 = 0;
remaining.i64 = 0;
elapsed.i64 = 0;
unsigned __int64 BytesRemaining = pForm->size - pForm->already_copied;
SYSTEMTIME SystemTime;
GetLocalTime(&SystemTime);
SystemTimeToFileTime(&SystemTime, &now.ft);
elapsed.i64 = now.i64 - StartTime.i64;
FileTimeToSystemTime(&elapsed.ft, &SystemTime);
pForm->LBisherdauer->Caption = pForm->FormatTime(&SystemTime);
remaining.i64 = ((BytesRemaining * (elapsed.i64/10000U)) /
(pForm->already_copied+1))*10000U;
DWORDLONG tmp;
if (remaining.i64>last.i64)
tmp = (remaining.i64-last.i64);
else
tmp = (last.i64-remaining.i64);
if (pForm->CGauge2->Progress>5)
{
remaining.i64 = (remaining.i64 + last.i64-tmp)/2;
FileTimeToSystemTime(&remaining.ft, &SystemTime);
pForm->LRestdauer->Caption = pForm->FormatTime(&SystemTime);
}
// letzter zeitwert
last.i64 = remaining.i64;
// Updaten
pForm->Update();
Application->ProcessMessages();
return PROGRESS_CONTINUE;
}
bool __fastcall TForm1::CopyTheFile(String source, String target)
{
BOOL bCancelled = FALSE;
return CopyFileEx(source.c_str(), target.c_str(),MyCopyProgressRoutine,
this, &bCancelled, COPY_FILE_RESTARTABLE);
}
tommy
 

{smallsort}

Re:copy files and directorys on recursiv way - directory folder problem

Tommy wrote:
<snip>
Quote
my only problem is the calculation of the time with is still need till the
copy proccess is finished. and the time which is elapsed since starting my
process.

the elapsed time since starting my proccess has a little error. it starts
mith 2 hours. 2 hours seems to be the initual value. but it have to start at
0.
The problem is that you call GetSystemTimeAsFileTime() to set the start
time, but use GetLocalTime() and SystemTimeToFileTime() to get the
current time in the progress routine. Since you're getting an immediate
difference of 2 hours that means your computer's probably set for a
timezone equivalent to UTC-2.
Since you're not concerned about what the time actually is, just how
much time has elaspsed since the operation started, why not just use
GetTickCount() to find the elapsed milliseconds? It'd make your code
simpler, more readable and easier to maintain.
--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur!"
 

Re:copy files and directorys on recursiv way - directory folder problem

Hi,
does this mean, when I set the timezone to UTC-2, that this problem is
solved, although I use GetSystemTimeAsFileTime, GetLocalTime and
SystemTimeToFileTime?
How can I set the timezone?
tommy
"Corey Murtagh" < XXXX@XXXXX.COM >schrieb im Newsbeitrag
Quote
Tommy wrote:

<snip>
>my only problem is the calculation of the time with is still need till
the
>copy proccess is finished. and the time which is elapsed since starting
my
>process.
>
>the elapsed time since starting my proccess has a little error. it
starts
>mith 2 hours. 2 hours seems to be the initual value. but it have to
start at
>0.

The problem is that you call GetSystemTimeAsFileTime() to set the start
time, but use GetLocalTime() and SystemTimeToFileTime() to get the
current time in the progress routine. Since you're getting an immediate
difference of 2 hours that means your computer's probably set for a
timezone equivalent to UTC-2.

Since you're not concerned about what the time actually is, just how
much time has elaspsed since the operation started, why not just use
GetTickCount() to find the elapsed milliseconds? It'd make your code
simpler, more readable and easier to maintain.

--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur!"
 

Re:copy files and directorys on recursiv way - directory folder problem

"Tommy" < XXXX@XXXXX.COM >wrote in message
Quote
does this mean, when I set the timezone to UTC-2, that this
problem is solved, although I use GetSystemTimeAsFileTime,
GetLocalTime and SystemTimeToFileTime?
As Corey already stated, if you change your code to use GetTickCount()
instead of SYSTEMTIME and FILETIME, then you don't have to worry about the
clock's settings at all.
Gambit
 

Re:copy files and directorys on recursiv way - directory folder problem

Tommy wrote:
Quote
Hi,

does this mean, when I set the timezone to UTC-2, that this problem is
solved, although I use GetSystemTimeAsFileTime, GetLocalTime and
SystemTimeToFileTime?
No, you'd have to set the timezone to UTC+0, or adjust for timezone
everywhere in your code. You're adjusting in one place and not the
other, which is the cause of the 2-hour bias you're seeing. On my
computer I'd be at a base 12-hour difference, 13 hours during local
daylight savings time.
But the crux of the matter is that you're using clock time to figure
elapsed time, when GetTickCount() will serve you much better.
Why do you need to know what the time actually is? The short answer is:
you /don't/ need to know the time, just the /elapsed/ time. You can use
GetTickCount() to find that simply, or you can fix you fouled-up time
checks.
Quote
How can I set the timezone?
You should /never/ adjust the timezone of the machine. Instead you
should write code that works regardless of the timezone setting.
--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur!"
 

Re:copy files and directorys on recursiv way - directory folder problem

Hi,
I just implement GetTickCount into my application can show me the number ob
seconds which have aleady gone.
after i have read the windows sdk, i have a question. there is following
info unter die gettickcount information:
"The elapsed time is stored as a DWORD value. Therefore, the time will wrap
around to zero if Windows is run continuously for 49.7 days. "
Does this mean, when I let my application run on a computer which runs
already 50 days, that my time calculation does not will work?
may you give me an example what this will say. if this function is limit to
50 days, i will need another way. but as i do not understand what they i do
not know if this funktion is good for me.
tommy
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >schrieb im
Newsbeitrag news:40e8645b$ XXXX@XXXXX.COM ...
Quote

"Tommy" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>does this mean, when I set the timezone to UTC-2, that this
>problem is solved, although I use GetSystemTimeAsFileTime,
>GetLocalTime and SystemTimeToFileTime?

As Corey already stated, if you change your code to use GetTickCount()
instead of SYSTEMTIME and FILETIME, then you don't have to worry about the
clock's settings at all.


Gambit


 

Re:copy files and directorys on recursiv way - directory folder problem

"Tommy" < XXXX@XXXXX.COM >wrote in message
Quote
Does this mean, when I let my application run on a
computer which runs already 50 days, that my time
calculation does not will work?
It simply means that when Windows itself has been running for more than 49.7
days, the value returned by GetTickCount() wraps back to 0. Unless you are
planning on copying files in a single operation for 49.7 days straight,
GetTickCount() works fine for calculating elapsed times. Just make sure
that you take the wrapping into account, ie:
DWORD start = GetTickCount();
//...
DWORD now = GetTickCount();
DWORD elasped;
if( now>= start )
elasped = (now - start);
else
elasped = ((0xFFFFFFFF - start) + now);
Gambit
 

Re:copy files and directorys on recursiv way - directory folder problem

Hi,
my copy opertation will not take more than 50 days. but the computers may
run perhabs the whole day. but know i will get the rest myself.
the time calculation for the elapsed time and the time which still will be
needed is now perfektly.
thanks for your help
tommy
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >schrieb im
Newsbeitrag news:40e9abc5$ XXXX@XXXXX.COM ...
Quote

"Tommy" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>Does this mean, when I let my application run on a
>computer which runs already 50 days, that my time
>calculation does not will work?

It simply means that when Windows itself has been running for more than
49.7
days, the value returned by GetTickCount() wraps back to 0. Unless you
are
planning on copying files in a single operation for 49.7 days straight,
GetTickCount() works fine for calculating elapsed times. Just make sure
that you take the wrapping into account, ie:

DWORD start = GetTickCount();

//...

DWORD now = GetTickCount();
DWORD elasped;

if( now>= start )
elasped = (now - start);
else
elasped = ((0xFFFFFFFF - start) + now);


Gambit


 

Re:copy files and directorys on recursiv way - directory folder problem

"Tommy" < XXXX@XXXXX.COM >wrote in message
Quote
my copy opertation will not take more than 50 days.
Then GetTickCount() will work just fine for getting the elapsed time of the
copy.
Quote
but the computers may run perhabs the whole day.
That makes no difference at all.
Gambit
 

Re:copy files and directorys on recursiv way - directory folder problem

Hi,
it works very fine, with all calculations. problem is, that the copy routine
needs much more time when i use the if statement to check if now>=
StartTime. this is not so nice.
is it perhabs possible tu deklare GetTickCount with 0, when starting the
copy process to avoid the extra if statement?
i also check my code for any optmization, but i counld not find anythink. is
there perhabs a better way the using GetTickCount or what can i do?
Here my copy routine code:
DWORD WINAPI MyCopyProgressRoutine(LARGE_INTEGER TotalFileSize,LARGE_INTEGER
TotalBytesTransferred,LARGE_INTEGER StreamSize,LARGE_INTEGER
StreamBytesTransferred,DWORD dwStreamNumber,DWORD dwCallbackReason,HANDLE
hSourceFile,HANDLE hDestinationFile,LPVOID lpData)
{
TForm1 *pForm = (TForm1*) lpData;
if (TotalFileSize.QuadPart>0)
{
// actual file status
unsigned __int64 Percent = (((unsigned
__int64)TotalBytesTransferred.QuadPart)*100) / ((unsigned
__int64)TotalFileSize.QuadPart);
pForm->CGauge1->Progress = Percent;
// all files status
pForm->tmp = (unsigned __int64)TotalBytesTransferred.QuadPart;
Percent = ((unsigned
__int64)((pForm->already_copied+pForm->tmp)*100))/(unsigned
__int64)(pForm->size);
pForm->CGauge2->Progress = Percent;
}
unsigned __int64 BytesRemaining = pForm->size - pForm->already_copied;
now = GetTickCount();
if(now>= StartTime)
{
elapsed = (now - StartTime);
}
else
{
elapsed = ((0xFFFFFFFF - StartTime) + now);
}
pForm->LBisherdauer->Caption = pForm->FormatTime(elapsed);
remaining = ((BytesRemaining * (elapsed)) / (pForm->already_copied+1));
pForm->LRestdauer->Caption = pForm->FormatTime(remaining);
// Updaten
pForm->Update();
Application->ProcessMessages();
return PROGRESS_CONTINUE;
}
i hope you have some ideas for me.
tommy
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >schrieb im
Newsbeitrag news:40e9d060$ XXXX@XXXXX.COM ...
Quote

"Tommy" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>my copy opertation will not take more than 50 days.

Then GetTickCount() will work just fine for getting the elapsed time of
the
copy.

>but the computers may run perhabs the whole day.

That makes no difference at all.


Gambit


 

Re:copy files and directorys on recursiv way - directory folder problem

"Tommy" < XXXX@XXXXX.COM >wrote in message
Quote
it works very fine, with all calculations. problem is, that the
copy routine needs much more time when i use the if statement
to check if now>= StartTime. this is not so nice.
Such small statements take almost no time at all to execute, so why is it
such a problem for you? If anything, you should get rid of the calls to
Application->ProcessMessages(), calling that as often as you are will slow
down your code a lot more than running a simple if() statement. If you
don't want to get rid of it altogether, you should at least not call it so
often. Call it maybe every 10 files, or every other directory, or something
like that.
Quote
is it perhabs possible tu deklare GetTickCount with 0, when
starting the copy process to avoid the extra if statement?
No.
Quote
i also check my code for any optmization, but i counld
not find anythink.
There is always optimizations that can be made to code.
Gambit