将ini文件添加为资源文件并从中读取

3
我想将一个ini文件作为资源文件添加到我的Delphi项目中。
我知道如何将文件添加为资源文件:
项目 > 资源和图像 > 添加
但是一旦完成这个步骤,我还需要做什么才能从文件中读取数据?我之前没有使用过资源文件。
有关此过程的文档吗?
谢谢。

为什么?如果你已经将配置添加到exe中,那么你也可以将其硬编码吗? - Uli Gerhardt
2
这里有一种从资源文件中获取文本信息的方法:如何将 TXT 文件添加到我的 EXE 文件资源中?使用流将其加载到 TMemIniFile 中。 - LU RD
4个回答

4
内置的RTL INI文件类(位于System.IniFiles单元中)要求INI文件是磁盘文件。因此,您可以将资源提取到磁盘上,然后从那里读取它。
如果您不喜欢这个想法,那么您可以编写自己的INI文件解析器,该解析器使用流而不是文件进行操作。您可以使用TMemIniFile的代码来指导您。复制该代码并将LoadValues替换为从流而不是文件读取的代码。或者,如果您足够努力,您可能会找到第三方INI解析器,该解析器使用流进行操作。
如果您准备考虑其他格式,那么您可以使用JSON而不是INI。内置的JSON解析器不需要输入数据驻留在磁盘上。它们可以在内存中的字符串上运行,听起来更加方便。
上面的文本实际上是无意义的。感谢Remy指出这一点。您可以使用TMemIniFile及其SetStrings方法解析不驻留在磁盘上的INI内容。步骤如下:
  • 将INI内容作为字符串放入资源中。
  • 将该资源加载到字符串变量中。
  • 创建一个TStringList,并将字符串变量分配给字符串列表的Text属性。
  • 创建一个TMemIniFile
  • TMemIniFile上调用SetStrings,传递字符串列表。
或者:
  • 将INI内容作为字符串放入资源中。
  • 创建一个TResourceStream对象来读取该资源。
  • 创建一个TStringList对象。
  • 在字符串列表上调用LoadFromStream,传递资源流。
  • 创建一个TMemIniFile
  • TMemIniFile上调用SetStrings,传递字符串列表。
尽管如此,选择这样做似乎有些奇怪。将配置信息硬编码到单元中作为一系列常量不是更简单吗?

2
RTL中内置的INI文件类提供了System.IniFiles单元,要求INI文件为磁盘文件 - TMemIniFile可以从TStrings(TMemIniFile.SetStrings())加载INI文件,TStringList可以从TStream(TStrings.LoadFromStream())加载,而TResourceStream可用于读取资源。 - Remy Lebeau
@RemyLebeau 谢谢 - David Heffernan

3
使用“资源和图像”对话框,将.ini文件作为RCDATA资源类型添加到项目中。然后,您可以在运行时像这样加载它:
uses
  ..., Classes, IniFiles;

var
  Ini: TMemIniFile;
  List: TStringList;
  Strm: TResourceStream;
begin
  Ini := TMemIniFile.Create;
  try
    List := TStringList.Create;
    try
      Strm := TResourceStream.Create(HInstance, 'ResourceIDHere', RT_RCDATA);
      try
        List.LoadFromStream(Strm);
      finally
        Strm.Free;
      end;
      Ini.SetStrings(List);
    finally
      List.Free;
    end;
    // use Ini as needed...
  finally
    Ini.Free;
  end;
end;

2
为了将文件添加到可执行文件中,请确保添加一个名为.rc的文件(而不是直接添加.ini文件),例如inis.rc(因此在源文件dpr中,您会有{$R 'inis.res' 'inis.rc'}),并在此文件中编写以下列表:
this 100 "this.ini"
that 100 "that.ini"

如果您将ini文件存储在相对目录中,请确保双倍反斜杠,因为这是C语法。(这里的100是资源类型,没有专门分配给ini文件的数字,所以我们将使用未分配的数字。下一个最好的东西是23,它被分配给RT_HTML,请参见下文)
如果您不使用组(只有[GroupName]的行),我建议您使用普通的TStringList对象和它们的Values属性。要加载它们的数据,请使用以下代码:
var
  sl:TStringList;
  r:TResourceStream;
begin
  sl:=TStringList.Create;
  try
    r:=TResourceStream.Create(HInstance,'this',MAKEINTRESOURCE(100));
    try
      sl.LoadFromStream(r);
    finally
      r.Free;
    end;

    //sl.Values['Setting']

  finally
    sl.Free;
  end;
end;

1
在我看来,应该使用MAKEINTRESOURCE代替Pointer - Uli Gerhardt
是的,但在Delphi中,我注意到声明在连续版本中在几个单位之间移动,因此我回退到使用指针转换使其在大多数情况下正常工作(具有相同的本质效果)。 - Stijn Sanders
你可以将TStringList加载到TMemIniFile中,从而进一步完善这个答案。 - Remy Lebeau
不错!我不知道那个。 - Stijn Sanders

1

在我看来,ini文件只是一个文本文件,用于与应用程序一起分发,以便您可以控制应用程序在特定环境中的行为。例如,您可以将语言存储在“language.ini”中,从源代码中读取它,并基于该语言呈现GUI界面。

为了实现这一点,您的ini文件包含:

[general]
language=Russian

然后在Delphi中读取它:
    ...
    uses Inifiles;
    ...
    var CurrentLanguage:string;
    ...    
    Ini := TIniFile.Create('C:\somedir\languages.ini');    
    CurrentLanguage := Ini.ReadString('General', 'language', 'English');//if key isn't found, language is English    
    Ini.free();

基本上它包含文本信息...如上所述,如果将其添加为资源,您可能会硬编码它。资源应主要用于二进制数据(图像、音频文件、视频等)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接