delphistreamtfilestreamtstream

TFileStream with offset


I need to extend TFileStream so that it can work with a file not from 0 offset, but from user defined offset. I mean it must interpret user defined offset as stream beginning. My code is:


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;
 

but it does not work propertly. The problem is in Seek function but I don't know why. When I pass such stream to a third party component it works only if TSuFileStream.Offset := 0;


Solution

  • Use TGpStreamWindow, available on my web and on Google Code.

    Usage:

    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;