📄 filesplitter.pas
字号:
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 + -