2012-03-07 10 views

risposta

12

Come ho letto la domanda che stai chiedendo di rimuovere il contenuto da un file a partire dall'inizio del file. In altre parole, si desidera eliminare il contenuto all'inizio del file e spostare il contenuto rimanente verso il basso.

Questo non è possibile. Puoi solo troncare un file dalla fine, non dall'inizio. Dovrai copiare il contenuto rimanente in un nuovo file o copiarlo nello stesso file.

Tuttavia, in questo modo non esiste un modo rapido ed efficiente per farlo. Devi copiare i dati, ad esempio come descrive @kobik.

Raymond Chen ha scritto un bel articolo su questo argomento: How do I delete bytes from the beginning of a file?


Solo per divertimento, ecco una semplice implementazione di un metodo basato sul flusso di eliminare il contenuto da qualsiasi parte del file. Si potrebbe usare questo con un flusso di file di lettura/scrittura. Non ho testato il codice, lo lascerò a te!

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; 
+0

In realtà, il riferimento al file sparse è piuttosto fuorviante. Non si tratta di ** cancellare ** N byte con offset 0, ma circa ** impostazione ** regione di 0..N-1 byte a zero (o qualunque valore del byte di riempimento preimpostato) – OnTheFly

+2

@user Spiacente, che cos'è ingannevole? –

+1

Sei fantastico! Grazie, David, l'ha fatto! – TheDude

7

Una soluzione molto semplice sarebbe quella di spostare (spostare) blocchi di dati dalla "posizione target compensare" verso BOF, e quindi tagliare (troncamento) gli avanzi:

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


-------------------------- 
|xxxxxx|yyyyyy|zzz|******| 
-------------------------- 
       ^EOF 

Dal @ David ha registrato un codice basato su TStream, qui è un codice in base a "basso livello" I O pascal stile /:

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; 
+2

** Idea molto astuta di Kobik, ma posso farlo in pratica? (in delhi intendo) – TheDude

+1

Certo che puoi: 'BlockRead' /' Cerca'/'BlockWrite' ... o usa' TFileStream' direttamente. – kobik

+0

@Gdhami Questo è tutto ciò che puoi fare. Devi copiare il contenuto rimanente del file. Il punto è che non esiste un modo semplice e banale di troncare all'inizio del file, a differenza del troncamento alla fine del file che è effettivamente gratuito. –

Problemi correlati