kopiowanie plików

0

Witam
Mam problem z kopiowaniem plików o dużych rozmiarach. Poniżej znajduje się procedura kopiująca która bez problemu radzi sobie z małymi plikami. Problem pojawia się jak chce skopiować plik o rozmiarze ok 4gb. Pasek postępu nic nie wskazuje i program tak jakby się zawiesza.
Jak sprawdziłem to w katalogu docelowym jest tworzony plik, czyli kopiuje sie , z tym ze trwa to całą wieczność. Po 20 minutach zaledwie niecały 1gb się skopiował. Może ktoś mi pomóc i oświecić dlaczego tak długo to trwa? Jakieś rozwiązanie tego problemu?

FUNCTION TBackup.CopyFile(CopyFrom,CopyTo : String):string;
var
Source, Dest : TFileStream;
toCopy : Longint;
FBytesCopied,FProcessed : Integer;
const
ChunkSize : Integer = 8192;
begin
Result := '-';
FBytesCopied:=0; f1.Lab1.caption := plik;
try
source := TFileStream.Create( CopyFrom, fmOpenRead or fmShareDenyWrite );
try
Dest := TFileStream.Create( CopyTo, fmCreate );
try
repeat
if (Source.Size-Source.Position) < ChunkSize then toCopy := Source.Size-Source.Position else toCopy := ChunkSize;

    Dest.CopyFrom( source, toCopy ); Inc( FBytesCopied, toCopy );
    if Source.Size > 0 then FProcessed := Round(FBytesCopied*100/Source.Size) else FProcessed := 0;

    f1.Gauge.Value:=FProcessed;  
    Application.ProcessMessages;

    until Dest.Size = Source.Size;
  finally   end;

finally Dest.Free; end;
finally Source.Free; end;
Result:= 'ok';
end;

0
unit Unit2;

interface

uses
  Classes, Windows;

type
  TFileStreamProgress = class(TFileStream)
  private
    FProgress: Word;
    FOnProgress: TNotifyEvent;
    FBpS: LongWord;

    procedure DoProgress;
  public
    constructor Create(const FileName: string; Mode: Word); overload;
    constructor Create(const FileName: string; Mode: Word; Rights: Cardinal);
    overload;

    function CopyFrom(Source: TStream; Count: Int64): Int64;

    property Progress: Word read FProgress;
    property BpS: LongWord read FBpS;
    property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
  end;

implementation

{ TFileStreamProgress }

function TFileStreamProgress.CopyFrom(Source: TStream;
  Count: Int64): Int64;
const
  MaxBufSize = $F0000;
var
  BufSize, N: Integer;
  Buffer: PChar;
  Start: Cardinal;
begin
  Start := GetTickCount - 1;
  FProgress := 0;
  FBpS := 0;
  if Count = 0 then
  begin
    Source.Position := 0;
    Count := Source.Size;
  end;
  Result := Count;
  if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;
  GetMem(Buffer, BufSize);
  try
    while Count <> 0 do
    begin
      if Count > BufSize then N := BufSize else N := Count;
      Source.ReadBuffer(Buffer^, N);
      WriteBuffer(Buffer^, N);
      Dec(Count, N);
      FProgress := Round((Result - Count) / Result * 1000);
      FBpS := Trunc((Result - Count) / (GetTickCount - Start) * 1000); 
      DoProgress;
    end;
  finally
    FreeMem(Buffer, BufSize);
  end;
end;

constructor TFileStreamProgress.Create(const FileName: string; Mode: Word;
  Rights: Cardinal);
begin
  FProgress := 0;
  FBpS := 0;
  inherited Create(FileName, Mode, Rights);
end;

constructor TFileStreamProgress.Create(const FileName: string; Mode: Word);
begin
  FProgress := 0;
  FBpS := 0;
  inherited Create(FileName, Mode);
end;

procedure TFileStreamProgress.DoProgress;
begin
  if Assigned(FOnProgress) then
    FOnProgress(Self);
end;

end.

użycie

procedure TForm1.btn2Click(Sender: TObject);
var
  Dest: TFileStreamProgress;
  Source : TFileStream;
begin
  Source := TFileStream.Create('dupa\dupa.dupa', fmOpenRead or fmShareDenyWrite);
  Dest := TFileStreamProgress.Create('dupa\dupa\dupa.dupa', fmCreate);
  Dest.OnProgress := CopyOnProgress;
  try
    Dest.CopyFrom(Source, 0);
  finally
    Source.Free;
    Dest.Free;
  end;
end;

procedure TForm1.CopyOnProgress(Sender: TObject);
begin
  pb1.Position := (Sender as TFileStreamProgress).Progress;
  lbl1.Caption := IntToStr((Sender as TFileStreamProgress).Progress div 10)  + ' %';
  lbl2.Caption := Format('%f MB/s', [(Sender as TFileStreamProgress).BpS /
    1024 / 1024]);
  Application.ProcessMessages;
end;

możesz poekspertymentować z rozmiarem buffora (zmienna MaxBufSize)

testowane na plikach ~7GB i kopiuje z prędkością podobną do Exploratora i TotalCommandera

0

ok zaraz sprawdze:)

0

super dzięki Misiekd , o to właśnie mi chodziło - masz u mnie wirtualnego browarka [browar] :d

0

A ja mam trochę inny problem:
Ja próbuję skopiować plik z dysku sieciowego (mapowany z literą np X:, folder tylko do odczytu) tymi przykładami powyżej to zawsze rozmiar pliku źródłowego=0 wiec się nic nie kopiuje. A lokalne pliki kopiują się bez problemu. Dlaczego ?
A może strumienie w tym przypadku nie zadziałają ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0