我正在使用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;
我的问题是:
我在StringList中添加和删除(释放)TStream对象的方式是否正确?也许我需要首先释放Stream然后释放Object ??
我在FormDestroy事件中释放所有对象的方式是否正确?
当我尝试将流加载回Memo(Memo.Lines.LoadFromStream(TStream(List.Objects [Idx])))时,它不会加载,尽管Stream.Size高于零。我做错了什么?
答案 0 :(得分:3)
我不明白你对释放流然后是对象的建议。据我了解,你正在谈论的释放的对象是流。你不能在另一个之前销毁一个,因为只有一个对象,它是一个流。
在字符串列表中添加和删除流对象的方法很好。它们并不理想,但我会限制我的评论,因为Stack Overflow不是Code Review。
致电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