INI 文件在退出后不会保留值 - RAD Studio 10.4.2
INI File wont keep values after exit - RAD Studio 10.4.2
这个简单的代码运行了很长时间。但是现在它已经停止工作了。
应用程序启动后,它会加载 Combobox
last_city
中的最后一个位置。如果我更改 Combobox
的索引,last_city
也会更改。如果我读取值一切正常,直到我退出应用程序。但是在我退出应用程序和 运行 应用程序后,值又消失了。
知道为什么它停止工作了吗? google 的一些变化? Api 28(Android 9)。 RAD Studio 10.4.2
procedure TForm1.FormCreate(Sender: TObject);
var data: string;
begin
app_ini := TIniFile.Create(TPath.GetDocumentsPath + PathDelim + 'app.ini', TEncoding.ANSI);
data := app_ini.ReadString('nastaveni', 'last_city', '');
if data <> '' then // load last city
begin
cb_mesta.SetFocus;
cb_mesta.ItemIndex := StrToInt(data);
cb_mesta.OnChange(Self);
cb_mezi.ItemIndex := StrToInt(app_ini.ReadString('nastaveni', 'last_adr', ''));
cb_mezi.OnChange(Self);
ch_last.IsChecked := True;
end;
end;
procedure TForm1.ch_lastChange(Sender: TObject); // when change city i safe change to ini file
begin
if ch_last.IsChecked then
begin
app_ini.WriteString('nastaveni', 'last_city', IntToStr(cb_mesta.ItemIndex));
app_ini.WriteString('nastaveni', 'last_adr', IntToStr(cb_mezi.ItemIndex));
end
else
begin
app_ini.WriteString('nastaveni', 'last_city', '');
app_ini.WriteString('nastaveni', 'last_adr', '');
end;
end;
原因是新的 Delphi 而不是正确编写的应用程序。
第一种方式 (Remy Lebeau):app_ini.UpdateFile;
在写入新值之后,或者至少在退出应用程序之前
第二种方式(SilverWarior):app_ini.Free;
进入您的 Form1 OnDestroy 事件。
但我认为最好是他们两个,以确保保存价值。
谢谢大家的帮助。
查看您的代码,我没有在任何地方看到您调用 app_ini.Free
。
为什么这很重要?当您调用 app_ini.Free
时,将执行 TIniFile class 的析构函数。在释放其内存析构函数之前,还要确保对 TIniFile 对象所做的所有更改都在其销毁之前写入 INI 文件。
但是为什么这些更改没有在发生时立即写入 INI 文件?答案是性能。
您看到 INI 文件是基于文本的文件。当您向基于文本的文件添加新文本时,或者如果您将现有文本的一部分替换为另一个长度不同的文本,则该文本之后的所有文本都需要移动。这意味着您需要读取您要更改到内存中的点之后的所有文本进行更改,然后将您已读取到内存中的所有文本写回到文件中。这会产生很多额外的开销。
为了避免这种额外的开销,TIniFile 将其内容存储在内存中,并且仅在调用 TIniFile.UpdateFile
时才将更改写入文件。
为什么这在过去对您有效,而现在不再有效?
当 Delphi XE4 首次引入对移动平台的支持时,这些平台的内存管理器基于 ARC(自动引用计数)机制。
在基于 ARC 的内存管理中,内存管理器使用特定对象的引用计数来确定是否需要销毁它。每次引用特定对象时引用计数都会增加,每次 clear/remove 引用特定对象时引用计数都会减少。当引用计数达到零时,对象就会被销毁。
因此,在 Delphi XE4 的 Delphi 版本中,直到移动平台上的 Delphi 10.3,作为开发人员,您无需过多关注释放特定对象,因为这是由内存管理器自动完成的。
但是 Delphi 10.4 删除了 ARC 内存管理(接口和字符串仍然保留),目的是将内存管理与从未使用基于 ARC 的内存管理的 Windows 平台统一(接口和字符串除外)字符串)。
并且自从您最近迁移到 Delphi 10.4 后,用于将数据存储到 INI 文件中的代码过去工作正常,因为它依赖于基于 ARC 的内存管理,但现在停止正常工作。
PS: 我强烈建议你仔细检查你的整个代码,因为缺少 ARC 内存管理可能也会影响你的代码的其他部分,如果它被编写考虑到基于 ARC 的内存管理,因为该代码现在可能会产生内存泄漏,因为依赖于 ARC 销毁的对象现在可能不再被销毁。
这个简单的代码运行了很长时间。但是现在它已经停止工作了。
应用程序启动后,它会加载 Combobox
last_city
中的最后一个位置。如果我更改 Combobox
的索引,last_city
也会更改。如果我读取值一切正常,直到我退出应用程序。但是在我退出应用程序和 运行 应用程序后,值又消失了。
知道为什么它停止工作了吗? google 的一些变化? Api 28(Android 9)。 RAD Studio 10.4.2
procedure TForm1.FormCreate(Sender: TObject);
var data: string;
begin
app_ini := TIniFile.Create(TPath.GetDocumentsPath + PathDelim + 'app.ini', TEncoding.ANSI);
data := app_ini.ReadString('nastaveni', 'last_city', '');
if data <> '' then // load last city
begin
cb_mesta.SetFocus;
cb_mesta.ItemIndex := StrToInt(data);
cb_mesta.OnChange(Self);
cb_mezi.ItemIndex := StrToInt(app_ini.ReadString('nastaveni', 'last_adr', ''));
cb_mezi.OnChange(Self);
ch_last.IsChecked := True;
end;
end;
procedure TForm1.ch_lastChange(Sender: TObject); // when change city i safe change to ini file
begin
if ch_last.IsChecked then
begin
app_ini.WriteString('nastaveni', 'last_city', IntToStr(cb_mesta.ItemIndex));
app_ini.WriteString('nastaveni', 'last_adr', IntToStr(cb_mezi.ItemIndex));
end
else
begin
app_ini.WriteString('nastaveni', 'last_city', '');
app_ini.WriteString('nastaveni', 'last_adr', '');
end;
end;
原因是新的 Delphi 而不是正确编写的应用程序。
第一种方式 (Remy Lebeau):app_ini.UpdateFile;
在写入新值之后,或者至少在退出应用程序之前
第二种方式(SilverWarior):app_ini.Free;
进入您的 Form1 OnDestroy 事件。
但我认为最好是他们两个,以确保保存价值。
谢谢大家的帮助。
查看您的代码,我没有在任何地方看到您调用 app_ini.Free
。
为什么这很重要?当您调用 app_ini.Free
时,将执行 TIniFile class 的析构函数。在释放其内存析构函数之前,还要确保对 TIniFile 对象所做的所有更改都在其销毁之前写入 INI 文件。
但是为什么这些更改没有在发生时立即写入 INI 文件?答案是性能。
您看到 INI 文件是基于文本的文件。当您向基于文本的文件添加新文本时,或者如果您将现有文本的一部分替换为另一个长度不同的文本,则该文本之后的所有文本都需要移动。这意味着您需要读取您要更改到内存中的点之后的所有文本进行更改,然后将您已读取到内存中的所有文本写回到文件中。这会产生很多额外的开销。
为了避免这种额外的开销,TIniFile 将其内容存储在内存中,并且仅在调用 TIniFile.UpdateFile
时才将更改写入文件。
为什么这在过去对您有效,而现在不再有效?
当 Delphi XE4 首次引入对移动平台的支持时,这些平台的内存管理器基于 ARC(自动引用计数)机制。
在基于 ARC 的内存管理中,内存管理器使用特定对象的引用计数来确定是否需要销毁它。每次引用特定对象时引用计数都会增加,每次 clear/remove 引用特定对象时引用计数都会减少。当引用计数达到零时,对象就会被销毁。
因此,在 Delphi XE4 的 Delphi 版本中,直到移动平台上的 Delphi 10.3,作为开发人员,您无需过多关注释放特定对象,因为这是由内存管理器自动完成的。
但是 Delphi 10.4 删除了 ARC 内存管理(接口和字符串仍然保留),目的是将内存管理与从未使用基于 ARC 的内存管理的 Windows 平台统一(接口和字符串除外)字符串)。
并且自从您最近迁移到 Delphi 10.4 后,用于将数据存储到 INI 文件中的代码过去工作正常,因为它依赖于基于 ARC 的内存管理,但现在停止正常工作。
PS: 我强烈建议你仔细检查你的整个代码,因为缺少 ARC 内存管理可能也会影响你的代码的其他部分,如果它被编写考虑到基于 ARC 的内存管理,因为该代码现在可能会产生内存泄漏,因为依赖于 ARC 销毁的对象现在可能不再被销毁。