TStream作为StringList中的对象

时间:2015-07-20 21:36:56

标签: delphi tstringlist tstream

我正在使用Delphi 7并使用StringList,以TStream作为对象。

我的测试项目有一个ListBox,一个Memo和2个按钮(Add and Remove)。

这是我到目前为止所得到的:

var
  List: TStringList;

procedure TForm1.FormCreate(Sender: TObject);
begin
  List := TStringList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  I: Integer;
begin
  if (List.Count > 0) then
    for I := 0 to Pred(List.Count) do
    begin
      List.Objects[I].Free;
      List.Objects[I] := nil;
    end;
  FreeAndNil(List);
end;

procedure TForm1.btnAddClick(Sender: TObject);
var
  Strm: TStream;
begin
  Strm := TMemoryStream.Create;
  try
    Memo.Lines.SaveToStream(Strm);
    List.AddObject(IntToStr(List.Count), TObject(Strm));
    Memo.Clear;
    ListBox.Items.Assign(List);
  finally
//    Strm.Free; (line removed)
  end;
end;

procedure TForm1.btnDelFirstClick(Sender: TObject);
begin
  if (List.Count > 0) then
  begin
    List.Objects[0].Free;
    List.Objects[0] := nil;
    List.Delete(0);    
    ListBox.Items.Assign(List);
  end;
end;

当我双击ListBox时,我想将所选项目Stream对象加载到Memo。这是我试图做的:

procedure TForm1.ListBoxDblClick(Sender: TObject);
var
  Idx: Integer;
begin
  Memo.Clear;
  Idx := ListBox.ItemIndex;
  if (Idx >= 0) and (TStream(List.Objects[Idx]).Size > 0) then
    Memo.Lines.LoadFromStream(TStream(List.Objects[Idx]));
end;

我的问题是:

  1. 我在StringList中添加和删除(释放)TStream对象的方式是否正确?也许我需要首先释放Stream然后释放Object ??

  2. 我在FormDestroy事件中释放所有对象的方式是否正确?

  3. 当我尝试将流加载回Memo(Memo.Lines.LoadFromStream(TStream(List.Objects [Idx])))时,它不会加载,尽管Stream.Size高于零。我做错了什么?

2 个答案:

答案 0 :(得分:3)

  1. 我不明白你对释放流然后是对象的建议。据我了解,你正在谈论的释放的对象是流。你不能在另一个之前销毁一个,因为只有一个对象,它是一个流。

  2. 在字符串列表中添加和删除流对象的方法很好。它们并不理想,但我会限制我的评论,因为Stack Overflow不是Code Review

  3. 致电SaveToStream后,信息流的位置位于信息流的 end 。如果要从流中读取,则必须再次将位置设置为开头。在调用Position := 0之前为流设置LoadFromStream

答案 1 :(得分:3)

  

1.我是否更正了在StringList中添加和删除(释放)TStream对象的方式?

是的,因为TStrings.Objects[]属性返回TObject指针而TStream派生自TObject,因此您可以在对象指针上调用Free()。< / p>

  

也许我需要首先释放Stream然后释放Object ??

在释放TStream对象之前,您需要释放TStringList个对象。正如你已经在做的那样。

  

2.我是否更正了释放FormDestroy事件中所有对象的方式?

是。虽然从技术上讲,在进入循环之前,您不需要检查TStringList.Count > 0属性,因为循环将为您处理该条件。在释放nil

之前,您不需要TStringList指针
procedure TForm1.FormDestroy(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to Pred(List.Count) do
    List.Objects[I].Free;
  List.Free;
end;

您正在做的一件事就是矫枉过正,无论何时添加/删除单个项目,Assign()都会将整个 TStringList TListBox添加到TStringList来自btnAddClick()。您应该简单地添加/删除ListBox中的关联项目,并按原样保留其余项目。

并向procedure TForm1.btnAddClick(Sender: TObject); var Strm: TStream; Idx: Integer; begin Strm := TMemoryStream.Create; try Memo.Lines.SaveToStream(Strm); Strm.Position := 0; Idx := List.AddObject(IntToStr(List.Count), Strm); except Strm.Free; raise; end; try ListBox.Items.Add(List.Strings[Idx]); except List.Objects[Idx].Free; List.Delete(Idx); raise; end; Memo.Clear; end; procedure TForm1.btnDelFirstClick(Sender: TObject); begin if List.Count > 0 then begin List.Objects[0].Free; List.Delete(0); ListBox.Items.Delete(0); end; end; 添加一些额外的错误检查,以避免在出现问题时发生任何内存泄漏。

试试这个:

Position
  

3.当我尝试将流加载回Memo(Memo.Lines.LoadFromStream(TStream(List.Objects [Idx])))时,尽管Stream.Size高于零,但它并没有加载。我做错了什么?

在将流加载到备忘录之前,您不会将流回到SaveToStream() 0。 LoadFromStream()始终将流保留在流的末尾,并且TListBox将流保留在负载停止读取的任何位置(如果不在最后,则发生故障)。

现在,尽管如此,我个人不会以这种方式使用Style。我会将其lbVirtual属性设置为OnData,然后使用其TStringList事件来显示TListBox中的字符串。无需直接将它们复制到TListBox,或尝试始终保持两个列表同步。让TStringList向你询问它所需的内容会更安全,并且使用更少的内存,然后你可以从TList提供它(然后我会改为OnData因为你并没有真正存储无法在var List: TList; procedure TForm1.FormCreate(Sender: TObject); begin List := TList.Create; end; procedure TForm1.FormDestroy(Sender: TObject); var I: Integer; begin ListBox.Count := 0; for I := 0 to Pred(List.Count) do TStream(List[I]).Free; List.Free; end; procedure TForm1.btnAddClick(Sender: TObject); var Strm: TStream; Idx: Integer; begin Strm := TMemoryStream.Create; try Memo.Lines.SaveToStream(Strm); Strm.Position := 0; Idx := List.Add(Strm); except Strm.Free; raise; end; try ListBox.Count := List.Count; except TStream(List[Idx]).Free; List.Delete(Idx); raise; end; Memo.Clear; end; procedure TForm1.btnDelFirstClick(Sender: TObject); begin if List.Count > 0 then begin TStream(List[0]).Free; List.Delete(0); ListBox.Count := List.Count; end; end; procedure TForm1.ListBoxDblClick(Sender: TObject); var Strm: TStream; Idx: Integer; begin Memo.Clear; Idx := ListBox.ItemIndex; if Idx >= 0 then begin Strm := TStream(List[Idx]); if Strm.Size > 0 then begin Strm.Position := 0; Memo.Lines.LoadFromStream(Strm); end; end; end; procedure TForm1.ListBoxData(Control: TWinControl; Index: Integer; var Data: string); begin Data := IntToStr(Index); end; 事件处理程序中动态生成的有意义的名称):

require "httparty"

File.open("file.jpg", "wb") do |tempfile| 
  tempfile.write HTTParty.get(params["avatar"]).parsed_response
  user.avatar.store!(tempfile)
end