使用 Delphi 将文本文件读入TStringList,但从下到上

ou6hu8tu  于 2023-02-04  发布在  其他
关注(0)|答案(3)|浏览(352)

我想反向读取一个文本文件,这样它会先从文本文件的底部读取。我确实找到了如何反向读取,但对我来说没有意义。有人能给我解释一下它是如何工作的吗?还有,如果有更好/更快的方法?它似乎在文件读取后完成所有工作,就像它会更快地从底部读取它。

var
  datalist : TStringList;
  lines,i  : Integer;
  saveLine : String;
begin
  datalist := TStringList.Create;
  datalist.LoadFromFile(filename);   //loads file
  lines := datalist.Count;

  for i := lines-1 downto (lines div 2) do
    begin
      saveLine := datalist[lines-i-1];
      datalist[lines-i-1] := datalist[i];
      datalist[i] := saveLine;
    end;
628mspwn

628mspwn1#

(At至少在 Delphi 7中是这样,但是更新的版本应该有类似的行为)

  1. .LoadFromFile()呼叫
  2. .LoadFromStream(),它将整个流/文件读入内存,然后调用
  3. .SetTextStr(),它只调用每条线路
  4. .Add()
    了解这一点有助于我们避免重新发明整个轮子,而是使用自己的类,并对.Add()方法进行一个细微的更改:
type
  TStringListReverse= class( TStringList )
    function Add( const S: String ): Integer; override;
  end;

function TStringListReverse.Add( const S: String ): Integer;
begin
  Result:= {GetCount} 0;  // Our change: always in front
  Insert( Result, S );
end;

现在我们使用自己的类:

var
  l: TStringListReverse;
begin
  l:= TStringListReverse.Create;
  l.LoadFromFile( 'C:\Windows\win.ini' );
  Memo1.Lines.Assign( l );
  l.Free;
uemypmqf

uemypmqf2#

正如我在评论中提到的,创建一个接受TStrings示例的适配器类,并将其公开为另一个TStrings,但是反过来,这可能是有用的。
这可能看起来像这样:

type
  TReversedStrings = class(TStrings)
  private
    FSource: TStrings;
    FOwnsSource: Boolean;
    function ReversedIndex(Index: Integer): Integer;
  protected
    procedure Put(Index: Integer; const S: string); override;
    function Get(Index: Integer): string; override;
    function GetCount: Integer; override;
    function GetObject(Index: Integer): TObject; override;
    procedure PutObject(Index: Integer; AObject: TObject); override;
  public
    constructor Create(Source: TStrings; AssumeOwnership: Boolean);
    destructor Destroy; override;
    procedure Clear; override;
    procedure Delete(Index: Integer); override;
    procedure Exchange(Index1, Index2: Integer); override;
    function IndexOf(const S: string): Integer; override;
    procedure Insert(Index: Integer; const S: string); override;
    procedure Move(CurIndex, NewIndex: Integer); override;
  end;

{ TReversedStrings }

constructor TReversedStrings.Create(Source: TStrings; AssumeOwnership: Boolean);
begin
  inherited Create;
  FSource := Source;
  FOwnsSource := AssumeOwnership;
end;

destructor TReversedStrings.Destroy;
begin
  if FOwnsSource then
    FSource.Free;
  inherited;
end;

function TReversedStrings.ReversedIndex(Index: Integer): Integer;
begin
  Result := FSource.Count - Index - 1;
end;

procedure TReversedStrings.Put(Index: Integer; const S: string);
begin
  FSource[ReversedIndex(Index)] := S;
end;

function TReversedStrings.Get(Index: Integer): string;
begin
  Result := FSource[ReversedIndex(Index)];
end;

function TReversedStrings.GetCount: Integer;
begin
  Result := FSource.Count;
end;

function TReversedStrings.GetObject(Index: Integer): TObject;
begin
  Result := FSource.Objects[ReversedIndex(Index)];
end;

procedure TReversedStrings.PutObject(Index: Integer; AObject: TObject);
begin
  FSource.Objects[ReversedIndex(Index)] := AObject;
end;

procedure TReversedStrings.Clear;
begin
  FSource.Clear;
end;

procedure TReversedStrings.Delete(Index: Integer);
begin
  FSource.Delete(ReversedIndex(Index));
end;

procedure TReversedStrings.Exchange(Index1, Index2: Integer);
begin
  FSource.Exchange(ReversedIndex(Index1), ReversedIndex(Index2));
end;

function TReversedStrings.IndexOf(const S: string): Integer;
begin
  Result := FSource.IndexOf(S);
  if Result > -1 then
    Result := ReversedIndex(Result);
end;

procedure TReversedStrings.Insert(Index: Integer; const S: string);
begin
  FSource.Insert(ReversedIndex(Index), S);
end;

procedure TReversedStrings.Move(CurIndex, NewIndex: Integer);
begin
  FSource.Move(ReversedIndex(CurIndex), ReversedIndex(NewIndex));
end;

如何使用它应该是显而易见的,我还没有测试代码,甚至没有执行它。

x3naxklr

x3naxklr3#

如果你想使用TStringList.LoadFromFile()函数,那么另一种方法是将一个TStringList复制到另一个TStringList,这将比当前的方案更快,并且代码行更少。

var
  datalist1, datalist2 : TStringList;
  lines, i: Integer;
  filename : string;
begin
  datalist1 := TStringList.Create;
  datalist2 := TStringList.Create;
  datalist1.LoadFromFile(filename);   //loads file
  lines := datalist1.Count;
  data2list.Capacity := lines;  // so it allocates the memory once
  for i := lines-1 downto 0 do
  begin
    datalist2.Add (datalist1[i]);
  end;

end;

就我个人而言,我会亲自阅读文件。

相关问题