Delete first N characters from TextFile without creating a new file (Delphi)

I just want to remove the first N characters from the specified text file, 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 am trying to use a TStringList, but additionally adds a line terminator.

 with TStringList.Create do try LoadFormFile(AFileName); // before - "Hello!" // even there are no changes... SaveToFile(AFileName); // after - "Hello!#13#10" finally Free; end; 

Thanks!

+6
delphi text-files pascal
source share
2 answers

There is no easy way to remove something from the beginning of a file in Windows. You must either copy the file to another file, delete the original and rename the target file, or copy all the data in the file with several bytes, and then trim the file. If the file is small and can be loaded into memory, the latter method becomes quite simple.

The following code snippet implements the latter approach with a full-sized 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; 
+9
source share

Gabr beat me, but I took a different 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 with 512 bytes to the file.

PS: this procedure only moves bytes, not characters! Thus, this only works for a single byte character.

+2
source share

All Articles