Tfilestream con offset.
-
12-11-2019 - |
Domanda
Ho bisogno di estendere il tflestream in modo che possa funzionare con un file non da 0 offset, ma da offset definito dall'utente.Voglio dire che deve interpretare l'utente definito dall'utente come lo streaming iniziale.Il mio codice è:
type
TSuFileStream = class(TFileStream)
protected
FOffset : int64;
procedure SetOffset(Offset : int64);
procedure SetSize(NewSize: Longint); override;
procedure SetSize(const NewSize: Int64); override;
public
constructor Create(const AFileName: string; Mode: Word); overload;
constructor Create(const AFileName: string; Mode: Word; Rights: Cardinal); overload;
function Seek(Offset: Longint; Origin: Word): Longint; override;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
property Offset : int64 read FOffset write SetOffset;
end;
...
constructor TSuFileStream.Create(const AFileName: string; Mode: Word);
begin
inherited Create(AFileName, Mode);
FOffset := 0;
end;
constructor TSuFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
begin
inherited Create(AFileName, Mode, Rights);
FOffset := 0;
end;
procedure TSuFileStream.SetOffset(Offset : int64);
begin
FOffset := Offset;
inherited Seek(FOffset, soBeginning);
end;
procedure TSuFileStream.SetSize(NewSize: Longint);
begin
inherited SetSize(FOffset + NewSize);
end;
procedure TSuFileStream.SetSize(const NewSize: Int64);
begin
inherited SetSize(FOffset + NewSize);
end;
function TSuFileStream.Seek(Offset: Longint; Origin: Word): Longint;
begin
Result := Seek(Int64(Offset), TSeekOrigin(Origin));
end;
function TSuFileStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
begin
case Origin of
soBeginning: Result := inherited Seek(FOffset + Offset, soBeginning) - FOffset;
soCurrent: Result := inherited Seek(Offset, soCurrent) - FOffset;
soEnd: Result := inherited Seek(Offset, soEnd) - FOffset;
end;
end;
.
Ma non funziona propriamente.Il problema è in funzione di ricerca ma non so perché.Quando passerò tale streaming a un componente di terze parti funziona solo se tsufelestream.offset:= 0;
Soluzione
Usa TGPStreamWindow , disponibile su Il mio web e su
Uso:
var
offsetStream: TGpStreamWindow;
begin
offsetStream := TGpStreamWindow.Create(originalStream, initialOffset, originalStream.Size - 1);
try
DoSomethingWith(offsetStream);
offsetStream.SetWindow(anotherInitialOffset, originalStream.Size - 1);
DoSomethingElseWith(offsetStream);
finally FreeAndNil(offsetStream); end;
end;
. Altri suggerimenti
In primo luogo, sovrasta solo una delle versioni del metodo. Come puoi vedere dall'interfaccia di classe hai sia versioni sia longint che INT64 degli stessi metodi (come SetSIze e Cerca). Questo è nella documentazione Delphi. Override le versioni INT64.
In secondo luogo, non avrei sovrascrivere il tflestream, ma piuttosto Tstream direttamente per creare un "tra flusso" con.
Nel costruttore avrei messo 2 parametri:
- .
- flusso di origine effettivo di qualsiasi tipo
- offset
Così fondamentalmente ciò che vuoi creare è un proxy tra il flusso reale e la versione personalizzata. In questo modo, nella tua ricerca implementazione tutto ciò che devi aggiungere l'offset (guarda TMEMORYStream e TFilestream per vedere come è fatto) alla posizione. Ottieni anche il vantaggio di supportare qualsiasi tipo di sorgente flusso.
Dovresti finire con un proxy che è facile da usare:
.mMyStream:=TMyProxyStream.Create(mRealStream,2800); //Root offset at 2800 try mMyStream.Read(mBuffer,1024); // After read, offset = 3824 mMyStream.position:=0; //Reset offset back to to 2800 finally mMyStream.free; end;
La funzionalità di ricerca può essere un po 'complicata da calcolare. Ecco un esempio da una classe proxy che ho codificato per il mio sistema di buffer (FoffSet è una variabile interna, questo è quello che vuoi manipolare):
.function TSLBufferStreamAdapter.Seek(const Offset:Int64; Origin:TSeekOrigin):Int64; Begin Case Origin of soBeginning: Begin if Offset>=0 then FOffset:=Math.EnsureRange(Offset,0,FBufObj.Size); end; soCurrent: Begin FOffset:=math.EnsureRange(FOffset + Offset,0,FBufObj.Size); end; soEnd: Begin If Offset>0 then FOffset:=FBufObj.Size-1 else FOffset:=math.EnsureRange(FOffset-(abs(Offset)),0,FBufObj.Size); end; end; result:=FOffset; end;
Aggiorno questa risposta ora per includere un link di aggiornamento. My Library Byterage è stato spostato in codice Google - Dai un'occhiata lì. Spero che ti aiuti!