[Back to COPYMOVE SWAG index] [Back to Main SWAG index] [Original]
{
> I need a QUICK way to Copy/Move files! (This must be able to
> work over Drives)
> the :
> Repeat
> BlockRead(...);
> BlockWrite(...);
> UNTIL ();
> Is To slow! How does MS-DOS do it?
Ok here is an example based on what I told you.
THIS IS TESTED CODE. CURRENTLY SET TO COMPILE IN PROTECTED MODE UNDER
BORLAND PASCAL 7.X. ALLMOST NO ERROR CHECKING IS DONE. IF THE PROGRAM
CAN'T AT LEAST ALLOCATE ONE BUFFER IT WILL CRASH AS NO CHECK IS MADE TO
SEE IF WE HAVE BUFFERS OR NOT
First a few numbers.
The following code managed to copy a > 10 MEG file at a rate of 640K/second
or about 300 clock ticks. That was acheived on a >10 Meg file, in a DOS BOX
under OS/2. Program reported 6.2 Meg of heap buffer used. That performance was
also across drives that reside on the same hard-disk ie: different partitions
of the same physical hard-disk which means head movement was unavoidable.
The target drive had 40Meg free. The same transfer from that drive to one
that had only 13 Meg free was 275K /Second which is still pretty good.
Here is the code:
}
program FastCopy;
{$A+,B-,D-,E+,F+,G+,I-,L-,N+,P-,Q-,R-,S-,T-,V-,X-,Y-}
{$M 16384,$10000}
const
MaxBufCnt = 1000;
type
BufPtr = ^BufRec;
BufRec = array[0..8190] of byte;
var
InFile, OutFile : file; {IF is In File, OF is OutFile}
Buffer : array[1..MaxBufCnt] of BufPtr;
BufLen : array[1..MaxBufCnt] of word;
BufSiz : array[1..MaxBufCnt] of word;
BufCnt : byte;
Total : longint;
SizeofFile : longint;
IndexR,IndexW : byte;
BytesWritten : word;
BR, BW : longint;
Timer1,Timer2 : longint;
Ticks : ^Longint;
begin
Ticks := Ptr(Seg0040, $006c);
if paramcount < 2 then begin
writeln('Usage:', paramstr(0), ' <Infile> <Outfile>');
halt;
end;
assign(InFile, paramstr(1));
assign(OutFile, paramstr(2));
writeln;
writeln('Copying ', paramstr(1), ' to ', paramstr(2));
reset(InFile, 1);
rewrite(OutFile, 1);
BufCnt := 0;
SizeOfFile := filesize(InFile);
Total := 0;
while (MaxAvail>8192) and (BufCnt<MaxBufCnt) and (Total<SizeOfFile) do begin
Inc(BufCnt);
if MaxAvail<32768 then
BufSiz[BufCnt] := MaxAvail
else
BufSiz[BufCnt] := 32768;
getmem(Buffer[BufCnt], BufSiz[BufCnt]);
BufLen[BufCnt] := 0;
Total := Total + BufSiz[BufCnt];
end;
writeln(Total:10, ' Bytes of buffer used');
BW := 0;
BR := 0;
Timer1 := Ticks^;
while not eof(InFile) do begin
IndexR := 0;
while (not eof(InFile)) and (IndexR < BufCnt) do begin
Inc(IndexR);
blockread(InFile, Buffer[IndexR]^, BufSiz[IndexR], BufLen[IndexR]);
BR := BR + BufLen[IndexR];
write(#13, BR:10, ' bytes read, ', BW:10, ' bytes written.');
end;
for IndexW := IndexR+1 to BufCnt do
BufLen[IndexW] := 0;
for IndexW := 1 to IndexR do begin
BlockWrite(OutFile, Buffer[IndexW]^, BufLen[IndexW], BytesWritten);
BW := BW + BytesWritten;
write(#13, BR:10, ' bytes read, ', BW:10, ' bytes written.');
if BytesWritten <> BufLen[IndexW] then begin
writeln;
writeln('Error writing to file... Disk might be full');
Halt;
end;
end;
end;
Close(InFile);
Close(OutFile);
Timer2 := ticks^;
writeln;
writeln('Copy took ', Timer2-Timer1, ' timer ticks to complete');
writeln('Throughput is ', SizeOfFile div (Timer2-Timer1), ' bytes/tick');
writeln('or if you prefer ', (SizeOfFile div (Timer2-Timer1)) * 18.2:8:0, '
bytes/second'); for IndexR := 1 to BufCnt do
freemem(Buffer[IndexR], BufSiz[IndexR]);
writeln;
writeln('Copy complete');
end.
{
Compile to PROTECTED MODE or modify accordingly. No need to reduce the Max
number of buffers. The program initializes it's buffers at the start to take
all available HEAP. The more DPMI memory the happyer it gets!!!
Again the logic here is to load as much of the file as possible so that you
don't keep moving the heads from the file you are copying to the copy you are
writing.
Note that the last few buffers won't be perfect multiples of 1024 but that
problem is overcompensated by the fact we are reading so many 32K buffers.
Give it a try and let me know what you think.
}
[Back to COPYMOVE SWAG index] [Back to Main SWAG index] [Original]