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;

È stato utile?

Soluzione

Usa TGPStreamWindow , disponibile su Il mio web e su codice Google . .

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:

    .
  1. flusso di origine effettivo di qualsiasi tipo
  2. 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!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top