我知道Ini文件仅用于单行信息,不用说我试图在Ini中读取/写入多行 - 没有太大的成功(我似乎总是这样做很难!)
让我们保存的Ini文件看起来像这样:
[richardmarx]
Filenames=hazard
children of the night
right here waiting
假设Ini文件是动态构建的(即,richardmarx和文件名不知道,但是唯一的 - 它们实际上可以是任何东西)。
我如何阅读Ini文件?
在这个例子中,我怎样才能将richardmarx放入TEdit,并将与richardmarx相关联的文件名放入备忘录?
非常感谢提前。
答案 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.ReadSection
或TMemIniFile.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.
中的每个部分名称会显示该部分中的项目,如下所示:
编辑:好的。我很好奇,看看它如何与您在问题中发布的ini文件内容一起使用。
所以我做了以下改变:
ListBox
末尾的新部分。执行代码,然后单击新的Sample.ini
项。这就是我得到的:
显然,那不行。所以我做了以下额外的更改:
richardmarx
事件更改为使用ListBox1Click
而非FIni.ReadSectionValues
。ReadSection
项以查看其显示方式,然后单击新C Section
项以查看其显示方式。结果如下:
答案 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它会返回一个带有节名称的字符串列表,其中每个项目的对象包含另一个带有节的字符串列表数据