- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Delphi 7 并使用 StringList,以 TStream 作为对象。
我的测试项目有一个列表框、一个备忘录和 2 个按钮(添加和删除)。
这是我到目前为止得到的:
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;
当我双击列表框时,我想将所选项目流对象加载到备忘录中。这是我尝试做的:
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 对象的方式正确吗?也许我需要先释放流,然后释放对象?
我在 FormDestroy 事件上释放所有对象的方式正确吗?
当我尝试将流加载回 Memo (Memo.Lines.LoadFromStream(TStream(List.Objects[Idx]))) 时,尽管 Stream.Size 大于零,但它不会加载。我做错了什么?
最佳答案
1.Is correct the way I am adding and removing (freeing) the TStream object inside the StringList?
是的,因为 TStrings.Objects[]
属性返回一个 TObject
指针,而 TStream
派生自 TObject
,因此您可以在对象指针上调用 Free()
。
Maybe I need to first free the Stream and then the Object??
您需要在释放 TStringList
对象之前释放 TStream
对象。正如您已经在做的那样。
2.Is correct the way I am freeing all objects on FormDestroy event?
是的。尽管从技术上讲,您不需要在进入循环之前检查 TStringList.Count
属性是否为 > 0
,因为循环将为您处理该条件。并且在释放 TStringList
之前,您不需要 nil
指针:
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
添加/删除单个项目时。您应该简单地从 ListBox 添加/删除关联的项目,并按原样保留剩余的项目。
并向 btnAddClick()
添加一些额外的错误检查,以避免出现问题时出现任何内存泄漏。
试试这个:
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;
3.When I try to load the stream back to Memo (Memo.Lines.LoadFromStream(TStream(List.Objects[Idx]))), it doesn't load, despite Stream.Size is higher than zero. What I am doing wrong?
在将流加载到备忘录之前,您不会将流返回到位置
0。 SaveToStream()
始终将流保留在流的末尾,而 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;
关于delphi - TStream 作为 StringList 内的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31526785/
要移动 TStream 类中的“当前字节”指针,我们可以使用属性 Position(例如 MyStream.Position := 0)或使用 Seek 方法(例如 MyStream.Seek(0,
TStream类包含许多 WriteData 的重载其形式如下: function WriteData(const Buffer: Int32; Count: Longint): Longint; o
我正在尝试将字符串转换为 TStream。下面的代码在 CopyFrom 行上给出了“抽象错误”消息。我在这里遇到了困难,有什么办法可以解决这个问题吗? procedure StringToStrea
通过 Indy 发送 TMemoryStream 的最佳方式是什么? 目前我正在尝试: procedure TClientForm.IdTCPClient1Connected(Sender: TObj
这是从 Apache Edgent Documentation 中获取的代码 我不明白元组到底是什么。代码如下: public static void main(String[] args) thro
我正在从流中读取组件,并且希望能够指定 Owner 属性。 var TComponent : comp; stream.Seek(0, soFromBeginning); comp :=
我正在使用 Delphi 7 并使用 StringList,以 TStream 作为对象。 我的测试项目有一个列表框、一个备忘录和 2 个按钮(添加和删除)。 这是我到目前为止得到的: var L
我的 MySQL 数据库上有一个存储过程,带有 2 个 Blob 类型的 OUT 参数 我想通过 UniDAC 的 SP 组件将它们的值作为 TStream 获取,我已尝试使用此代码进行测试: SP
当我尝试运行以下简单代码序列时,收到Abstract Error 错误消息: type TForm1 = class(TForm) Image1: TImage; Button1:
我编写了一个 DataSnap 服务器方法,它返回一个 TStream 对象来传输文件。客户端应用程序调用该方法并正常读取流。我的问题是,在 TStream 对象可供读取之前,方法调用需要一段时间才能
我正在 Delphi XE2 中使用 TCP/IP 协议(protocol)开发 DataSnap 项目,该项目需要将二进制数据流作为方法参数传递到服务器。我遇到的问题是流内容似乎有大约 32 KB
我需要从 Stream 中读取数据并将读取的缓冲区放入 OleVariant (VarArray) 变量中。 var MemoryStream : TMemoryStream; Data : OleV
我正在尝试使用 TBlobStream 方法将附件数据从 IMAP 服务器插入到 MySQL 数据库。 procedure TForm1.Button1Click(Sender: TObject);
我使用 Delphi XE2 构建了一个 DataSnap REST 服务器,并添加了一个通过 TStream 上传文件的服务器方法: function TServerMethods.updateUp
我正在使用 C++Builder,并且正在尝试慢慢地将代码迁移到使用 C++ 标准库而不是 Delphi VCL。 VCL 有一个基于 TStream 类的流架构,我正在改用 std::stream。
我有一个 Delphi 10.1 Berlin Datasnap 服务器,它无法返回大于大约 260.000 字节的数据包(通过 TStream)。 我按照 Delphi 的 \Object Pasc
我正在尝试编写一个 Delphi 控制台应用程序,为其标准输入创建一个 TStream,并为其标准输出创建另一个 TStream。 (它将由主机应用程序启动,其输入和输出重定向到管道,并将二进制数据传
我编写了一个 DataSnap 服务器方法,它返回一个 TStream 对象来传输文件。客户端应用程序调用该方法并读取流来下载文件。服务器方法非常简单: function TServerMethods
如下面代码的Test2所示,TStringList被转换为TStream,然后TStream又被转换回TStringList。然而,在 Delphi 7 中 Test2 给出的结果与 Test1 相同
对于 TStringStream,使用其 Bytes 属性的 bytes 与使用 TStream.Read 提取的 bytes 不同。如下图: 使用TStream.Read提取的字节代表正确的数据。
我是一名优秀的程序员,十分优秀!