开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜