Delete first N characters from TextFile without creating a new file (Delphi)
I just wanna to delete from specified 开发者_开发百科text file first N characters, but i'm stuck. Help me please!
procedure HeadCrop(const AFileName: string; const AHowMuch: Integer);
var
F: TextFile;
begin
AssignFile(F, AFileName);
// what me to do next?
// ...
// if AHowMuch = 3 and file contains"Hello!" after all statements
// it must contain "lo!"
// ...
CloseFile(F);
end;
I'm tried to use TStringList but its additionally appends end-line character!
with TStringList.Create do
try
LoadFormFile(AFileName); // before - "Hello!"
// even there are no changes...
SaveToFile(AFileName); // after - "Hello!#13#10"
finally
Free;
end;
Thanks!
There's no simple way to delete something from the start of file in Windows. You have to either copy the file to another file, delete the original and rename the target file or copy all the data in the file few bytes back and then truncate the file. If the file is small and can be loaded into memory, the latter method becomes quite simple.
The following code fragment implements the latter approach with a full-size memory buffer.
var
fs: TFileStream;
ms: TMemoryStream;
begin
fs := TFileStream.Create('somefile', fmOpenReadWrite); // catch errors here!
try
ms := TMemoryStream.Create;
try
ms.CopyFrom(fs, 0);
ms.Position := 42; // head bytes to skip
fs.Position := 0;
fs.CopyFrom(ms, ms.Size - ms.Position);
fs.Size := fs.Position;
finally FreeAndNil(ms); end;
finally FreeAndNil(fs); end;
end;
Gabr beat me to it, but I took another approach:
procedure HeadCrop(const AFileName: string; const AHowMuch: Int64);
var
lFileStream: TFileStream;
lPos: Int64;
lRead: Integer;
lBuffer: array[0..511] of Byte;
begin
lFileStream := TFileStream.Create(AFileName, fmOpenReadWrite);
try
if lFileStream.Size < AHowMuch then
begin
lFileStream.Size := 0;
Exit;
end;
lPos := AHowMuch;
repeat
lFileStream.Position := lPos;
lRead := lFileStream.Read(lBuffer, SizeOf(lBuffer));
lFileStream.Position := lPos - AHowMuch;
lFileStream.Write(lBuffer, lRead);
Inc(lPos, SizeOf(lBuffer));
until lRead <> SizeOf(lBuffer);
lFileStream.Size := lFileStream.Size - AHowMuch;
finally
lFileStream.Free;
end;
end;
This code reads the file and moves blocks of 512 bytes back in the file.
PS: this procedure only moves bytes, NOT characters! So this only works for one byte characters.
精彩评论