Ini文件 - 读取多行?

时间:2011-11-11 00:04:05

标签: delphi ini

我知道Ini文件仅用于单行信息,不用说我试图在Ini中读取/写入多行 - 没有太大的成功(我似乎总是这样做很难!)

让我们保存的Ini文件看起来像这样:

[richardmarx] 
Filenames=hazard
children of the night
right here waiting

假设Ini文件是动态构建的(即,richardmarx和文件名不知道,但是唯一的 - 它们实际上可以是任何东西)。

我如何阅读Ini文件?

在这个例子中,我怎样才能将richardmarx放入TEdit,并将与richardmarx相关联的文件名放入备忘录?

非常感谢提前。

8 个答案:

答案 0 :(得分:14)

不要将多行字符串存储到INI文件中。逃避换行符,就像@RobertFrank建议的那样。不过,我不会使用asterik,因为那是一个有效的文本字符。我会用这样的东西代替:

[richardmarx] 
Filenames=hazard%nchildren of the night%nright here waiting

然后,您可以读取字符串并将%n序列替换为sLineBreak全局变量的值。如果您需要存储实际的%字符,请将其转义为%%,例如:

[sales] 
value=Sale! 50%% off%nat Macy's

答案 1 :(得分:6)

您没有使用有效的.ini格式,因此这并不容易。如果使用格式正确的.ini文件,则会更容易。

有效ini文件的格式为

[section]
akey=value
bkey=value
ckey=value

以下是从ini文件中读取多行的示例。虽然它使用的是TListBox而不是TEdit,但它应该足以让您入门。

下面的代码也适用于格式不正确的文件,但您可能需要更改ListBox1Click事件中的代码才能使用ReadSectionValues,并为每个项目进行一些手动解析在展示之前;在这种情况下,在事件处理程序中创建另一个TStringList并传递它而不是Memo1.Lines

使用格式正确的ini文件,您可以使用TIniFile.ReadSectionTMemIniFile.ReadSections将所有部分加载到TStrings后代,然后使用{{1}获取每个部分的值。

以下是一个示例 - 将此ReadSection(SectionName)文件保存在某处(我使用过ini

d:\temp\sample.ini

以下是表单代码的示例:

[A Section]
Item1=Item A1
Item2=Item A2
Item3=Item A3
Item4=Item A4

[B Section]
Item1=Item B1
Item2=Item B2
Item3=Item B3
Item4=Item B4

[C Section]
Item1=Item C1
Item2=Item C2
Item3=Item C3
Item4=Item C4

点击unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, IniFiles; type TForm2 = class(TForm) ListBox1: TListBox; Memo1: TMemo; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure ListBox1Click(Sender: TObject); private { Private declarations } FIni: TMemIniFile; public { Public declarations } end; var Form2: TForm2; implementation {$R *.dfm} const IniName = 'd:\Temp\Sample.ini'; procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction); begin FIni.Free; end; procedure TForm2.FormCreate(Sender: TObject); begin FIni := TMemIniFile.Create(IniName); Memo1.Lines.Clear; FIni.ReadSections(ListBox1.Items); end; procedure TForm2.ListBox1Click(Sender: TObject); var Section: string; begin if ListBox1.ItemIndex > -1 then begin Section := ListBox1.Items[ListBox1.ItemIndex]; FIni.ReadSection(Section, Memo1.Lines); end; end; end. 中的每个部分名称会显示该部分中的项目,如下所示:

Application Screen Capture

编辑:好的。我很好奇,看看它如何与您在问题中发布的ini文件内容一起使用。

所以我做了以下改变:

  • 将您的样本ini内容逐字复制并粘贴到我在上面创建的ListBox末尾的新部分。

执行代码,然后单击新的Sample.ini项。这就是我得到的:

Sample image 2

显然,那不行。所以我做了以下额外的更改:

  • richardmarx事件更改为使用ListBox1Click而非FIni.ReadSectionValues
  • 运行已修改的应用程序,然后单击ReadSection项以查看其显示方式,然后单击新C Section项以查看其显示方式。结果如下:

Image with C Section selected Image with richardmarx selected

答案 2 :(得分:4)

预处理.ini文件!更改]和[之间的所有换行符到一些永远不会出现在文件名中的字符(如星号)。然后使用TInifile访问刚刚预处理的文件,在检索字符串后将星号更改回换行符。 (使用StringReplace

如果您在一个部分中有多个标识符,那就比这复杂一点。在这种情况下,您可以使用等号作为标记,不应删除前面的换行符。也许你从头到尾阅读文件。

你甚至可以创建一个TIniFile的后代,为你做一个更换线路的改变。

不,这肯定不是一个优雅的解决方案。但是,如果你被卡住,有时像这样的暴力行为!这里的其他解决方案可能更好,但我想我会分享这个,以防它给你一个思考标题的方向......

答案 3 :(得分:2)

使用任何 TStrings 后代对象,您只需使用 CommaText 属性即可将所有行读取和写入单个字符串。

MyStrings.CommaText := IniFile.ReadString('Section', 'Ident');

IniFile.WriteString('Section', 'Ident', MyStrings.CommaText);

CommaText 非常聪明,可以通过自动用引号括起逗号来处理包含逗号的行。

答案 4 :(得分:2)

此代码显示如何使用INI文件

编写和读取多行
procedure TForm1.SaveButtonClick(Sender: TObject);
begin
  IniFile.WriteString('Name', 'FirtName', FirstName.Text);
  IniFile.WriteString('Name', 'LastName', LastName.Text);
  IniFile.WriteInteger('Alpha Blend', 'Alpha Blend Value', Form1.AlphaBlendValue);
//Here start save Memo Lines
  LinesCount := AboutMemo.Lines.Count;
  IniFile.WriteInteger('About', 'Lines Count', LinesCount);
  for I := 0 to LinesCount-1 do
  IniFile.WriteString('About', 'About'+IntToStr(I), AboutMemo.Lines[i]);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin;
  GetCurrentDir;
  IniFile := TIniFile.Create(ChangeFileExt(Application.ExeName, '.ini'));
  FirstName.Text := IniFile.ReadString('Name', 'FirstName', '');
  LastName.Text := IniFile.ReadString('Name', 'LastName', '');
  Form1.AlphaBlendValue := IniFile.ReadInteger('Alpha Blend', 'Alpha Blend Value', 255);
//Here Start Read Memo Lins From INI File
  LinesCount := IniFile.ReadInteger('About', 'Lines Count', 0);
  for I := 0 to LinesCount-1 do
  AboutMemo.Lines.Insert(I, IniFile.ReadString('About', 'About'+IntToStr(I), ''));
end;
end.

答案 5 :(得分:1)

我想要类似的东西,在ini文件中包含自动电子邮件的正文 但我也想在身体上留下空白线条。这是ini文件的一部分

[EmailBody]
This is the weekly Survey Status notification email.
.
It lists Survey Reports that may need some attention.
.
The purpose of this information is to improve conduct-of-operations in our tracking, 
recordkeeping, and maintenance of Survey Reports.  This report will also enable 
us to identify any changes made to electronic Surveys following the normal QA review.
.
Please review your information weekly and determine if you need to take corrective action.

这是我最终做的事情

var
  Config: TMemIniFile;
  sl: TStringList;
...
  sl := TStringList.Create;
  Config.ReadSectionValues('EmailBody', sl);
  for i := 0 to sl.Count - 1 do
    if sl[i] = '.' then
      sl[i] := '';

答案 6 :(得分:1)

@Ken White

FIni.ReadSectionValues 在相同的键后获取完整的字符串,例如" key = value"。

.ini

[B Section]
Item1=Item B1
Item B2
Item B3
Item4=Item B4

之后

FIni.ReadSectionValues('B Section',Memo1.Lines);

Memo1.Lines {' Item1 = Item B1',' Item4 = Item B4'}


不幸的是,我们无法直接读取值,没有任何密钥。 但事实上,它并不太难:

procedure TForm2.FormCreate(Sender: TObject);
var i:longint;
strtemp: TStringList;
begin
  FIni := TMemIniFile.Create(IniName);
  Memo1.Lines.Clear;
  Fini.ReadSection('B Section',strtemp);
for i:=0 to strtemp.Count-1 do
  Memo1.Items.Add(Fini.ReadString('B Section',strtemp[i],''));
end;

Memo1.Lines 将是 {'项目B1','项目B4'}

Upper方法将读取部分中的所有值,不带键。 如何阅读非键控值 - 我不知道(如果可能的话, .ini )。 作为一个巨大的非格式 .ini 的解决方案,只需计算所有字符串 - 读取文件,如文本文件,找到所需的部分,并添加相同的计数索引,如键,示意(!):

FileString[i]:=inttostr(i)+'='+FileString[i];

如果需要混合格式,则需要更复杂的解析器。

P.S。对不起我的英语,我不是很坚强。

答案 7 :(得分:0)

您可以使用ReadSections方法获取ini文件中的所有部分名称。

也许您可以使用TMemIniFile's ReadSectionValues方法来读取“多行值”(即将整个部分读入字符串列表)。如果这不起作用那么也许你可以使用GetStrings获取ini文件的内容并“手动解析” - IIRC它会返回一个带有节名称的字符串列表,其中每个项目的对象包含另一个带有节的字符串列表数据