⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filesplitter.pas

📁 delphi下的大文件分割控件,在网站有VC++的,这里传一个delphi的
💻 PAS
📖 第 1 页 / 共 2 页
字号:
    if not FOutDifferent then
      FSplitFileName := ChangeFileExt(Value, '.SPL');
  end;
end;

{ Sets the name of the first split file - all other split files will
  have the same name, with extensions .001, .002, .003 etc. }
procedure TFileSplitter.SetSplitFileName(Value: TFileName);
begin
  if Value <> FSplitFileName then
  begin
    FSplitFileName := Value;
    FOutDifferent := True;
  end;
end;

{ Sets the maximum size of split files }
procedure TFileSplitter.SetSize(Value: LongInt);
begin
  if Value <> FSize then
    FSize := Value;
end;

{ Sets the maximum size of the first split file }
procedure TFileSplitter.SetReduceFirstSizeBy(Value: LongInt);
begin
  if Value <> FReduceFirstSizeBy then
    if (FSize - SizeOf(Signature) - Value) > 0 then
      FReduceFirstSizeBy := Value;
end;

{ Sets the buffer size }
procedure TFileSplitter.SetBufferSize(Value: Integer);
begin
  if Value <> FBufferSize then
    FBufferSize := Value;
end;

{ Component constructor... }
constructor TFileSplitter.Create(AOwner: TComponent);
begin
  inherited;
  FFileName := '';
  FSplitFileName := FFileName;
  FOutDifferent := False;
  FSize := 1457664;
  FBufferSize := 1457664;
  FReduceFirstSizeBy := 0;
  Signature.Copyright := 'TFileSplitter by Jovan Sedlan';
  Signature.NumberOfFiles := 0;
end;

{ EraseFile deletes a file on disk }
procedure EraseFile(FN: TFileName);
var
  f: File;

begin
  AssignFile(f, FN);
  Erase(f);
end;

{ StrZero returns a string representation of a Number,
  Len characters long, with leading zeroes }
function StrZero(Number: LongInt; Len: Byte): String;
var
  Temp: String;

begin
  Temp := Trim(IntToStr(Number));
  Result := StringOfChar('0', Len - Length(Temp)) + Temp;
end;

{ Split method does the actual work - splits a file into multiple files }
procedure TFileSplitter.Split;
var
  i: Integer;
  Continue: Boolean;
  FileCount, PercentDone: Integer;
  sFileName: TFileName;
  BytesToRead, BytesWritten, BytesRead, BytesStored, LastSplitFileSize: LongInt;
  TheSize: LongInt;

begin
  if FileExists(FFileName) then
  begin
    { Make sure the filename is correct }
    if FSplitFileName = '' then
      FSplitFileName := ChangeFileExt(FFileName, '.SPL');

    { Prepare for reading from file }
    FFile := TFileStream.Create(FFileName, fmOpenRead);
    GetMem(FBuffer, FBufferSize);

    { Calculate the number of resulting files }
    FileCount := (FFile.Size + SizeOf(Signature)) div FSize;
    LastSplitFileSize := (FFile.Size + SizeOf(Signature)) mod FSize;
    if LastSplitFileSize <> 0 then
      Inc(FileCount);
    if (LastSplitFileSize + FReduceFirstSizeBy) > FSize then
      Inc(FileCount);
    Signature.NumberOfFiles := FileCount;

    try
      { Write resulting file(s) }
      i := 1;
      Continue := True;
      sFileName := FSplitFileName;
      while (i <= FileCount) do
      begin
        if Assigned(FOnNeedDisk) then
          FOnNeedDisk(Self, i, Signature.NumberOfFiles, Continue);

        if Continue then
        begin
          { Delete the resulting file if it exists }
          if FileExists(sFileName) then
            EraseFile(sFileName);
          FSplitFile := TFileStream.Create(sFileName, fmCreate);

          BytesWritten := 0;
          if i = 1 then
          begin
            { Put the signature in the first split file }
            FSplitFile.Write(Signature, SizeOf(Signature));
            { Write one file }
            BytesToRead := FBufferSize;
            if BytesToRead > FSize - FReduceFirstSizeBy then
              BytesToRead := FSize - FReduceFirstSizeBy;

            BytesToRead := BytesToRead - SizeOf(Signature);
            BytesWritten := SizeOf(Signature);

            { Real size of the split file }
            TheSize := FSize - FReduceFirstSizeBy;
          end
          else
          begin
            { Write one file }
            BytesToRead := FBufferSize;
            if BytesToRead > FSize then
              BytesToRead := FSize;

            { Real size of the split file }
            TheSize := FSize;
          end;

          while BytesWritten < TheSize do
          begin
            if BytesToRead > TheSize - BytesWritten then
              BytesToRead := TheSize - BytesWritten;
            BytesRead := FFile.Read(FBuffer^, BytesToRead);
            BytesStored := FSplitFile.Write(FBuffer^, BytesRead);
            Inc(BytesWritten, BytesStored);

            { Call OnProgress event }
            if Assigned(FOnProgress) then
            begin
              if i = FileCount then
                PercentDone := (BytesWritten * 100) div LastSplitFileSize
              else
                PercentDone := (BytesWritten * 100) div TheSize;
              FOnProgress(Self, PercentDone);
            end;

            if FFile.Position = FFile.Size then
              Break;
          end;
          FSplitFile.Free;
          sFileName := ChangeFileExt(sFileName, '.' + StrZero(i, 3));
          Inc(i);
        end;
      end;
    finally
      { Clean up }
      FreeMem(FBuffer);
      FFile.Free;
    end;
  end
  else
    raise EFileError.Create('Input file ''' + FFileName + ''' does not exist.');
end;

{ Method UnSplit creates the original file from the split files. Name and
  extension of the original file must be set in FileName property }
procedure TFileSplitter.UnSplit;
var
  i: Integer;
  Continue: Boolean;
  sFileName: TFileName;
  BytesRead, TotalRead: LongInt;

begin
  if FileExists(FSplitFileName) then
  begin
    { Make sure the filename is correct }
    if FFileName = '' then
      FFileName := ChangeFileExt(FSplitFileName, '.XXX');

    { Delete the resulting file if it exists }
    if FileExists(FFileName) then
      EraseFile(FFileName);

    { Prepare for writing to file }
    FFile := TFileStream.Create(FFileName, fmCreate);
    GetMem(FBuffer, FBufferSize);

    try
      i := 0;
      sFileName := FSplitFileName;

      { Read files one by one and write to resulting file }
      Continue := True;
      Signature.NumberOfFiles := 0;
      while Continue do
      begin
        if Assigned(FOnNeedDisk) then
          FOnNeedDisk(Self, i + 1, Signature.NumberOfFiles, Continue);

        if Continue then
        begin
          if FileExists(sFileName) then
          begin
            try
              FSplitFile := TFileStream.Create(sFileName, fmOpenRead);

              { Read the signature from the first split file }
              if i = 0 then
                FSplitFile.Read(Signature, SizeOf(Signature));

              TotalRead := 0;
              while FSplitFile.Size <> FSplitFile.Position do
              begin
                BytesRead := FSplitFile.Read(FBuffer^, FBufferSize);
                FFile.Write(FBuffer^, BytesRead);
                TotalRead := TotalRead + BytesRead;

                { Call OnProgress event }
                if Assigned(FOnProgress) then
                  FOnProgress(Self, (TotalRead * 100) div FSplitFile.Size);
              end;
            finally
              FSplitFile.Free;
            end;
            Inc(i);
            sFileName := ChangeFileExt(sFileName, '.' + StrZero(i, 3));
          end
          else
            Continue := False;
        end;
      end;
    finally
      FreeMem(FBuffer);
      FFile.Free;
    end;
  end
  else
    raise EFileError.Create('Input file ''' + FSplitFileName + ''' does not exist.');
end;

{ Register component and property editors }
procedure Register;
begin
  RegisterComponents('SEDLAN A.D.', [TFileSplitter]);
  RegisterPropertyEditor(TypeInfo(TFileName), TFileSplitter, 'FileName', TFSFileNameProperty);
  RegisterPropertyEditor(TypeInfo(TFileName), TFileSplitter, 'SplitFileName', TFSSplitFileNameProperty);
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -