是否可以从文件的开头删除字节?

The*_*ude 9 delphi truncate file

我知道我可以有效地截断文件并从文件末尾删除字节.

是否有相应的有效方法通过将文件开头的内容删除到文件中间的某个位来截断文件?

Dav*_*nan 12

在我阅读您要求从文件开头的文件中删除内容时,我正在阅读这个问题.换句话说,您希望删除文件开头的内容并将剩余内容向下移动.

这是不可能的.您只能从末尾截断文件,而不是从头开始截断.您需要将剩余的内容复制到新文件中,或者在同一文件中自行复制.

但是,你这样做没有捷径有效的方法来做到这一点.您必须复制数据,例如@kobik描述.

Raymond Chen写了一篇关于这个主题的好文章:如何从文件开头删除字节?


只是为了好玩,这里是一个基于流的方法的简单实现,用于从文件中的任何位置删除内容.您可以将其与读/写文件流一起使用.我没有测试过代码,我会留给你的!

procedure DeleteFromStream(Stream: TStream; Start, Length: Int64);
var
  Buffer: Pointer;
  BufferSize: Integer;
  BytesToRead: Int64;
  BytesRemaining: Int64;
  SourcePos, DestPos: Int64;
begin
  SourcePos := Start+Length;
  DestPos := Start;
  BytesRemaining := Stream.Size-SourcePos;
  BufferSize := Min(BytesRemaining, 1024*1024*16);//no bigger than 16MB
  GetMem(Buffer, BufferSize);
  try
    while BytesRemaining>0 do begin
      BytesToRead := Min(BufferSize, BytesRemaining);
      Stream.Position := SourcePos;
      Stream.ReadBuffer(Buffer^, BytesToRead);
      Stream.Position := DestPos;
      Stream.WriteBuffer(Buffer^, BytesToRead);
      inc(SourcePos, BytesToRead);
      inc(DestPos, BytesToRead);
      dec(BytesRemaining, BytesToRead);
    end;
    Stream.Size := DestPos;
  finally
    FreeMem(Buffer);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

  • @user对不起,有什么误导? (2认同)

kob*_*bik 7

一个非常简单的解决方案是将数据块从" 目标位置偏移 " 转移(移动)到BOF,然后修剪(截断)剩余部分:

--------------------------
|******|xxxxxx|yyyyyy|zzz|
--------------------------
BOF  <-^ (target position offset)


--------------------------
|xxxxxx|yyyyyy|zzz|******|
--------------------------
                  ^ EOF
Run Code Online (Sandbox Code Playgroud)

由于@David发布了一个代码TStream,这里有一些基于"低级"I/O pascal风格的代码:

function FileDeleteFromBOF(const FileName: string; const Offset: Cardinal): Boolean;
var
  Buf: Pointer;
  BufSize, FSize,
  NumRead, NumWrite,
  OffsetFrom, OffsetTo: Cardinal;
  F: file;
begin
  {$IOCHECKS OFF}
  Result := False;
  AssignFile(F, FileName);
  try
    FileMode := 2; // Read/Write
    Reset(F, 1); // Record size = 1
    FSize := FileSize(F);
    if (IOResult <> 0) or (Offset >= FSize) then Exit;
    BufSize := Min(Offset, 1024 * 64); // Max 64k - This value could be optimized
    GetMem(Buf, BufSize);
    try
      OffsetFrom := Offset;
      OffsetTo := 0;
      repeat
        Seek(F, OffsetFrom);
        BlockRead(F, Buf^, BufSize, NumRead);
        if NumRead = 0 then Break;
        Seek(F, OffsetTo);
        BlockWrite(F, Buf^, NumRead, NumWrite);
        Inc(OffsetFrom, NumWrite);
        Inc(OffsetTo, NumWrite);
      until (NumRead = 0) or (NumWrite <> NumRead) or (OffsetFrom >= FSize);
      // Truncate and set to EOF
      Seek(F, FSize - Offset);
      Truncate(F);
      Result := IOResult = 0;
    finally
      FreeMem(Buf);
    end;
  finally
    CloseFile(F);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

  • 图片为+1.这应该消除OP存在的确切需要的不确定性. (3认同)
  • **非常聪明的想法Kobik,但我可以在实践中这样做吗?(在德尔福我的意思是) (2认同)