Recent

Author Topic: larger Tstringlist Capacity  (Read 28021 times)

Chronos

  • Full Member
  • ***
  • Posts: 240
    • PascalClassLibrary
Re: larger Tstringlist Capacity
« Reply #15 on: May 27, 2010, 12:29:11 am »
In my view TFileStream is better because
  • it is more clear and consistent object style using "namespace" and resource identification as object itself
  • so it is more abstract with some information hiding, portability, extensibility, ...
  • thanks to its ancestor TStream it have common behaviour with TMemoryStream, TStringStream, TResourceStream and any other custom streams used for data serialization

Anyway, function and effectivity should be the same. In fact, methods like Read and Write are implemented using FileRead and FileWrite, method Seek as FileSeek and constructor use FileOpen, FileCreate and destructor using FileClose. So these are API calls and they are portable probably.

Another older approach was using procedures as Assign(AssignFile), Rewrite, Reset, Close(CloseFile), Erase, Append, Read, Write and which are located in unit system. It was easy and clear for old ages but now with object pascal we can take advantage of some OOP features.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: larger Tstringlist Capacity
« Reply #16 on: May 29, 2010, 03:36:42 pm »
Maybe this works:

Code: [Select]
function TTextFileStream.EditLine(Line :integer; NewText :string):string;
var
  n, i :integer;
  s :string;
  Buffer :string;
  BytesRead :integer;
  FileLength :integer;
  FilePos :integer;
begin
  Result := '';
  n := 0;
  s := '';
  BytesRead := 1;
  while (n <= Line) and not eof do
  begin
    s := Readln;
    Inc(n);
  end;
  FilePos := Position;
  FileLength := Seek(0, soEnd);
  Seek(FilePos, soBeginning);
  SetLength(Buffer, FileLength + 2);
  BytesRead := Read(Buffer[1], FileLength - FilePos);
  SetLength(Buffer, BytesRead);
  NewText := NewText +#13#10;
  Seek(FilePos - Length(s) - 2, soBeginning);
  Write(NewText[1], Length(NewText));
  Write(Buffer[1], BytesRead);
  SetSize(FilePos - Length(s) - 2 + BytesRead + Length(NewText));
  Result := s;
end;     
« Last Edit: July 04, 2010, 11:42:11 am by typo »

mas steindorff

  • Hero Member
  • *****
  • Posts: 526
Re: larger Tstringlist Capacity
« Reply #17 on: May 29, 2010, 05:44:16 pm »
thanks typo (and all others).  I'll give this a try when I get funding for a second pass at the project.  It's working now with tstrings so I'll let it ride as is since I have some other projects on my plate.  Need to leave room to re-WOW the end user 8)
windows 7/10 - laz 2.0 / 1.2.6 general releases

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11080
  • FPC developer.
Re: larger Tstringlist Capacity
« Reply #18 on: May 30, 2010, 05:48:19 am »
TFileStream saves you from having to do many operations of  I/O.

I've always found that kind of statements highly doubtable.

Sure, streams can be great in the sense that they abstract the streams somewhat (and you can use the same code to write to a memory stream as filestream), but the normal operations are IMHO only more difficult or the same.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: larger Tstringlist Capacity
« Reply #19 on: September 03, 2010, 02:05:00 am »
Revised file:

Code: [Select]
unit UTextFileStream;

{$mode Delphi}{$H+}

interface

uses Classes, SysUtils, Dialogs;

type
  TTextFileStream = class(TFileStream)
  private
    FBuffer: string;
    //FLineLength :integer;
  public
    function Eof: Boolean;
    function WriteLn(Text: string):int64;
    function ReadLn: string;
    function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
    function RowCount: Integer;
    function EditLine(Line :integer; NewText :string):string;
  end;

implementation

{ TTextFileStream }

const
  NewLine = #13#10;

function TTextFileStream.Eof: Boolean;
begin
  Eof := Position - Length(FBuffer) = Size;
end;

function TTextFileStream.ReadLn: string;
const
  BufferLength = 10000;
var
  NewBuffer: string;
  Readed: Integer;
begin
  Readed := 1;
  while (Pos(#13, FBuffer) = 0) and (Readed > 0) do begin
    SetLength(NewBuffer, BufferLength + 2);
    Readed := Read(NewBuffer[1], BufferLength);
    SetLength(NewBuffer, Readed);
    FBuffer := FBuffer + NewBuffer;
  end;
  if Pos(#13, FBuffer) > 0 then begin
    Result := Copy(FBuffer, 1, Pos(#13, FBuffer) - 1);
    Delete(FBuffer, 1, Pos(#13, FBuffer) + 1);
  end else begin
    Result := FBuffer;
    FBuffer := '';
  end;
end;

function TTextFileStream.RowCount: Integer;
begin
  Result := 0;
  FBuffer := '';
  Seek(0, soBeginning);
  while not Eof do begin
    ReadLn;
    Inc(Result);
  end;
  Seek(0, soBeginning);
end;

function TTextFileStream.Seek(const Offset: Int64;
  Origin: TSeekOrigin): Int64;
begin
  if Origin = soCurrent then
    Result := inherited Seek(Offset - Length(FBuffer), Origin)
    else Result := inherited Seek(Offset, Origin);
  FBuffer := '';
end;

function TTextFileStream.WriteLn(Text: string):int64;
begin
  Result := 0;
  if Seek(0, soCurrent) > 0 then
    Write(NewLine, Length(NewLine));
  Write(Text[1], Length(Text));
  Result := RowCount;
end;

function TTextFileStream.EditLine(Line :integer; NewText :string):string;
var
  n :integer;
  s :string;
  Buffer :string;
  BytesRead :integer;
  FileLength :integer;
  FilePos :integer;
begin
  Result := '';
  n := 0;
  s := '';
  BytesRead := 1;
  FilePos := 0;
  while (n <= Line) and not Eof do
  begin
    s := Readln;
    Inc(n);
    FilePos := FilePos + Length(s) + Length(NewLine);
  end;
  if Line >= n then
    raise Exception.Create('Line index out of bounds.');
  //FilePos := Position;
  FileLength := Seek(0, soEnd);
  Seek(FilePos, soBeginning);
  SetLength(Buffer, FileLength + Length(NewLine));
  BytesRead := Read(Buffer[1], FileLength - FilePos);
  SetLength(Buffer, BytesRead);
  NewText := NewText + NewLine;
  Seek(int64(FilePos) - int64(Length(s)) - int64(Length(NewLine)), soBeginning);
  Write(NewText[1], Length(NewText));
  Write(Buffer[1], BytesRead);
  SetSize(FilePos - Length(s) - Length(NewLine) + BytesRead + Length(NewText));
  Result := s;
end;

end.                 

 

TinyPortal © 2005-2018