INI 文件读写
filecreate('路径加文件名');//创建一个文件。
(1) INI文件的结构:
;这是关于INI文件的注释部分
[节点]
关键字=值
...
INI文件允许有多个节点,每个节点又允许有多个关键字, “=”后面是该关键字的值(类型有三种:字符串、整型数值和布尔值。其中字符串存贮在INI文件中时没有引号,布尔真值用1表示,布尔假值用0表示)。注释以分号“;”开头。
(2) INI文件的操作
1、 在Interface的Uses节增加IniFiles;
2、 在Var变量定义部分增加一行:inifile:Tinifile;然后,就可以对变量myinifile进行创建、打开、读取、写入等操作了。
3、 打开INI文件:inifile:=Tinifile.create('tmp.ini');
4、 读取关键字的值:
a:=inifile.Readstring('节点','关键字',缺省值);// string类型
b:=inifile.Readinteger('节点','关键字',缺省值);// integer类型
c:=inifile.Readbool('节点','关键字',缺省值);// boolean类型
其中[缺省值]为该INI文件不存在该关键字时返回的缺省值。
5、 写入INI文件:
inifile.writestring('节点','关键字',变量或字符串值);
inifile.writeinteger('节点','关键字',变量或整型值);
inifile.writebool('节点','关键字',变量或True或False);
当这个INI文件的节点不存在时,上面的语句还会自动创建该INI文件。
6、 删除关键字:
inifile.DeleteKey('节点','关键字');//关键字删除
inifile.EraseSection('节点');// 节点删除
7、 节点操作:
inifile.readsection('节点',TStrings变量);//可将指定小节中的所有关键字名读取至一个字符串列表变量中;
inifile.readsections(TStrings变量);//可将INI文件中所有小节名读取至一个字符串列表变量中去。
inifile.readsectionvalues('节点',TStrings变量);//可将INI文件中指定小节的所有行(包括关键字、=、值)读取至一个字符串列表变量中去。
8、 释放:inifile.distory;或inifile.free;
创建了一个myini.ini文件,有一个名为newini的小节,有3个关键字“用户名称”“已运行时间”“是否正式用户”。运行效果,可以在edit1里边填入“用户名称”;edit2显示时间,不可以改变数值;checkbox1通过打勾,保存时间和“用户名称”进入myini.ini文件里边,重新打开应用程序时,显示的时保存下来的时间和填入的“用户名称”,如果在myini.ini文件里边修改,效果和在程序运行过程中修改时一样的。
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,inifiles, StdCtrls, ExtCtrls; {调用inifiles 类} type TForm1 = class(TForm) Label1: TLabel; Label2: TLabel; Label3: TLabel; Edit1: TEdit; Edit2: TEdit; Timer1: TTimer; CheckBox1: TCheckBox; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation var myinifile:TInifile; {定义一个类的实例} {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); var filename:string; begin {下面两行的书写形式,在应用程序的路径下创建ini文件} filename:=ExtractFilePath(paramstr(0))+'myini.ini'; myinifile:=TInifile.Create(filename); edit1.Text:=myinifile.ReadString('newini','用户名称','胡长浩'); edit2.text:=inttostr(myinifile.readinteger ('newini','已运行时间',0)); checkbox1.Checked:=myinifile.readbool ('newini','是否正式用户',False); {newini是小节名字,中间字段是关键字的名字,第三个字段是缺省值。当myini.ini不存在时,上面的语句自动创建这个文件,上边几行里的引号是单引号} end; procedure TForm1.FormDestroy(Sender: TObject); begin myinifile.writestring('newini','用户名称',edit1.Text); myinifile.writeinteger('newini','已运行时间', strtoint(edit2.text)); myinifile.writebool('newini','是否正式用户', checkbox1.Checked); myinifile.Destroy; end; procedure TForm1.Timer1Timer(Sender: TObject); begin edit2.Text:=inttostr(strtoint(edit2.text)+1); end; end.
使用 TIniFile
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Button6: TButton; Button7: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure Button6Click(Sender: TObject); procedure Button7Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses IniFiles; {uses 包含 TIniFile 的单元} var ini: TIniFile; path: string; {ini 文件路径} Section,Key: string; {分别表示 ini 文件的小节与关键字} { ini文件结构: ;注释 [小节名] 关键字=值 INI文件支持: string、integer、boolean、Date、Time、DateTime、Double 与二进制类型 string 值没有引号 boolean 的真假用 1、0 表示 } procedure TForm1.FormCreate(Sender: TObject); begin path := ChangeFileExt(ParamStr(0),'.ini'); ini := TIniFile.Create(path); {ini 对象建立需要文件路径参数, 如果缺少路径会默认Windows目录} end; //写入 ini 文件: procedure TForm1.Button1Click(Sender: TObject); begin Section := 'AAA'; Key := 'AString'; ini.WriteString(Section,Key,'AAA-String'); Key := 'AInteger'; ini.WriteInteger(Section,Key,111); Key := 'ABoolean'; ini.WriteBool(Section,Key,True); Key := 'ADate'; ini.WriteDate(Section,Key,Now); Key := 'ATime'; ini.WriteTime(Section,Key,Now); Key := 'ADateTime'; ini.WriteDateTime(Section,Key,Now); Key := 'ADouble'; ini.WriteFloat(Section,Key,Pi); Section := 'BBB'; Key := 'BString'; ini.WriteString(Section,Key,'BBB-String'); Key := 'BInteger'; ini.WriteInteger(Section,Key,222); Key := 'BBoolean'; ini.WriteBool(Section,Key,True); Key := 'BDate'; ini.WriteDate(Section,Key,Now); Key := 'BTime'; ini.WriteTime(Section,Key,Now); Key := 'BDateTime'; ini.WriteDateTime(Section,Key,Now); Key := 'BDouble'; ini.WriteFloat(Section,Key,Pi); Section := 'CCC'; Key := 'CString'; ini.WriteString(Section,Key,'CCC-String'); Key := 'CInteger'; ini.WriteInteger(Section,Key,333); Key := 'CBoolean'; ini.WriteBool(Section,Key,False); Key := 'CDate'; ini.WriteDate(Section,Key,Now); Key := 'CTime'; ini.WriteTime(Section,Key,Now); Key := 'CDateTime'; ini.WriteDateTime(Section,Key,Now); Key := 'CDouble'; ini.WriteFloat(Section,Key,Pi); {写入结果: [AAA] AString=AAA-String AInteger=111 ABoolean=1 ADate=2007-12-17 ATime=22:06:23 ADateTime=2007-12-17 22:06:23 ADouble=3.14159265358979 [BBB] BString=BBB-String BInteger=222 BBoolean=1 BDate=2007-12-17 BTime=22:06:23 BDateTime=2007-12-17 22:06:23 BDouble=3.14159265358979 [CCC] CString=CCC-String CInteger=333 CBoolean=0 CDate=2007-12-17 CTime=22:06:23 CDateTime=2007-12-17 22:06:23 CDouble=3.14159265358979 } end; //读取 ini 文件: procedure TForm1.Button2Click(Sender: TObject); var s: string; i: Integer; b: Boolean; f: Double; d: TDate; t: TTime; dt: TDateTime; begin s := ini.ReadString('BBB','BString',''); {最后一个参数是默认值} i := ini.ReadInteger('BBB','BInteger',0); b := ini.ReadBool('BBB','BBoolean',False); f := ini.ReadFloat('BBB','BDouble',0); d := ini.ReadDate('BBB','BDate',Now); t := ini.ReadTime('BBB','BTime',Now); dt := ini.ReadDateTime('BBB','BDateTime',Now); ShowMessage(s); {BBB-String} ShowMessage(IntToStr(i)); {222} ShowMessage(BoolToStr(b)); {-1(True)} ShowMessage(FloatToStr(f)); {3.14159265358979} ShowMessage(DateToStr(d)); {2007-12-17} ShowMessage(TimeToStr(t)); {22:06:23} ShowMessage(DateTimeToStr(dt)); {2007-12-17 22:06:23} end; //读入所有小节名到 TStrings: procedure TForm1.Button3Click(Sender: TObject); var List: TStrings; begin List := TStringList.Create; ini.ReadSections(List); ShowMessage(List.Text); { AAA BBB CCC } List.Free; end; //读入指定小节的所有关键字到 TStrings: procedure TForm1.Button4Click(Sender: TObject); var List: TStrings; begin List := TStringList.Create; ini.ReadSection('AAA',List); ShowMessage(List.Text); { AString AInteger ABoolean ADate ATime ADateTime ADouble } List.Free; end; //读入指定小节的所有关键字与值到 TStrings: procedure TForm1.Button5Click(Sender: TObject); var List: TStrings; begin List := TStringList.Create; ini.ReadSectionValues('BBB',List); ShowMessage(List.Text); { BString=BBB-String BInteger=222 BBoolean=1 BDate=2007-12-17 BTime=22:06:23 BDateTime=2007-12-17 22:06:23 BDouble=3.14159265358979 } List.Free; end; //删除与添加 procedure TForm1.Button6Click(Sender: TObject); begin ini.DeleteKey('BBB','BString'); {删除关键字} ini.EraseSection('CCC'); {删除小节} // ini.UpdateFile; {保存到文件} {添加小节与关键字或修改值, 直接写入即可} end; //其他功能 procedure TForm1.Button7Click(Sender: TObject); var b: Boolean; s: string; begin b := ini.SectionExists('DDD'); {判断某个小节是否存在} b := ini.ValueExists('AAA','AString'); {判断某个关键字的值是否存在} s := ini.FileName; {获取文件名} end; procedure TForm1.FormDestroy(Sender: TObject); begin ini.Free; end; end. ini 文件操作记要(2): 使用 TMemIniFile unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses IniFiles; var ini: TMemIniFile; procedure TForm1.FormCreate(Sender: TObject); begin ini := TMemIniFile.Create('c: emp est.ini'); end; //写入 procedure TForm1.Button1Click(Sender: TObject); begin ini.WriteString('AAA','A1','AAA-String'); //其他也都和 IniFile 一样使用 // ini.WriteInteger(); // ini.WriteBool(); // ini.WriteDate(); // ini.WriteTime(); // ini.WriteDateTime(); // ini.WriteFloat(); // ini.WriteBinaryStream(); //ini.UpdateFile; //因为 TMemIniFile 是内存操作, 这样才能保存到文件 end; //读出及其他 procedure TForm1.Button2Click(Sender: TObject); var s: string; begin s := ini.ReadString('AAA','A1','默认值'); ShowMessage(s); //AAA-String //其他读入命令也都和 IniFile 一样使用 // ini.ReadInteger(); // ini.ReadBool(); // ini.ReadDate(); // ini.ReadTime(); // ini.ReadDateTime(); // ini.ReadFloat(); // ini.ReadBinaryStream(); //还有四个常用方法也是和 IniFile 一样的 //ini.DeleteKey(); //ini.EraseSection(); //ini.ReadSection(); //ini.ReadSections(); //另外有三个 IniFile 中没有的方法也容易使用 //ini.GetStrings(List: TStrings); //ini.SetStrings(List: TStrings); //ini.Rename(const FileName: string; Reload: Boolean); //其中 Rename 中的第二个 Boolean 参数如果为 True 将会刷新读入 end; procedure TForm1.FormDestroy(Sender: TObject); begin ini.Free; end; end.
web桌面ini
var Cmd:string; Cmd:=myinifile.readstring('Shell','Cmd','App_Sys'); Cmd:=LeftStr(URL,7) Copy(URL,9,length(URL))
利用INI文件实现界面无闪烁多语言切换
熊斌 landragon@tom.com
一、引言
越来越多的程序使用了多国语言切换,虽然DELPHI自带多语言包的添加和配置,但是那种方法在切换语言时界面会出现闪烁,而且实现起来很麻烦,这里我介绍给大家的是利用INI文件来读取界面的语种文字,用这种方法,不但简单易行,而且在切换的时候不会出现界面的闪烁。
二、InI文件格式说明
1、语种定义
[Language] //语言
DefaultLang = ChineseGB //界面的默认语种(InI文件名,不带扩展名)
Language = 语种 //菜单标题
ChineseGB = 简体中文 //相应语种文件名
ChineseBig = 繁体中文
English = 英文
⑴ 如果DefaultLang项没有设置,则为语种目录中所寻找到的InI的第一个文件,做为当前界面语种,所有Ini文件都要设置成一样;
⑵ Language为菜单界面上所显示的标题,不设置时,默认为‘Language’;
⑶ 如果Language以下项没有设置,则相应语种的菜单标题为文件名(不带扩展名)。
2、窗体界面定义
[FormName] //需要变换的窗口
.Caption = 演示窗体 //本窗口的属性,表示为:[窗口名].属性名 = 语言
Button1.Hint = 按钮说明 //控件的属性,表示为:控件名.属性名 = 语言
ComboBox1.Items = 简体中文||英文 //其中“||”为分隔符
注:⑴ 在InI文件中每行“//”开始的说明文字不要输入;
⑵ 对继承自TStrings的属性,其各个项目之间需用“||”分隔;
⑶ 设计思想来源于KeyZhang所编写的《多语言切换函数 For Delphi》组件。
三、实现原理
RTTI的基本设计思想是在运行时访问给定数据类型的信息,该类型可以是类也可以是简单的Pascal数据类型(int、string、char等)。本文便是通过RTTI在运行期,获取组件的相应属性,并进行动态设置,达到多语言切换功能。
四、各个函数的定义及实现
1、程序运行时,我们查找语种目录下所有的语言配置文件(*.ini),为了达到这个目的,我编写了如下的函数搜索目录下所有的语言配置文件的文件名,然后将文件名去掉ini扩展名保存返回:
procedure SearchLanguagePack (lngStrings: TStrings); var DosError: Integer; SearchRec: TsearchRec; begin DosError := FindFirst (ExtractFilePath (ParamStr (0)) 'Language*.ini', faAnyFile, SearchRec); while DosError = 0 do begin { 返回的文件名并去掉末尾的.ini字符 } lngStrings.Add (ChangeFileExt (SearchRec.Name, '')); DosError := FindNext (SearchRec); end; FindClose(SearchRec); end;
2、实现界面的多语言切换函数:
function ChangeLanguage (Form: TForm; Lngfile: string): Boolean; var INIF: TIniFile; //InI文件 SL: TStringList; // InI文件中读出的相应窗体的信息 TmpSL: TStringList; //将每一行信息,以“=”分隔的信息 Key: string; //“=”左边的信息 Value: string; //“=”右边的信息 CompName: string; //组件名 CompProp: string; //组件属性名 I: Integer; AComponent: TComponent; //相应组件 procedure Split (S: string; SplitChar: string; R: TStrings); //将字符串分隔 var P, L, C: Integer; begin R.Clear; L := Length (S); //确定分隔符的长度,以便删除字符串中的相应字符 C := Length (SplitChar); //循环分隔字符串 repeat P := Pos (SplitChar, S); //如果在字符串中没有找到分隔符,说明为最后一个 if P = 0 then C := 1; R.Add (Copy (S, P C, L)); Delete(S, P, L); until P = 0; end; //设置相应属性值 procedure SetPropertyValue (AComponent: TComponent; sProperty, sValue: string); var PropInfo: PPropInfo; AStrings: TStringList; begin if AComponent <> nil then begin PropInfo := GetPropInfo(AComponent, sProperty); if PropInfo <> nil then begin case PropInfo.PropType^.Kind of tkString, tkLString: //字符串属性 SetStrProp(AComponent, PropInfo, sValue); tkInteger: //序数属性 SetOrdProp(AComponent, PropInfo, StrToInt(sValue)); else if PropInfo.PropType^.Name = 'TStrings' then //列表属性 begin AStrings := TStringList.Create; try Split (sValue, '||', AStrings); SetOrdProp (AComponent, PropInfo, Integer (AStrings)); finally AStrings.Free; end; // end try end; // end if PropInfo.PropType^.Name = 'TStrings' end; // end case end; // end if PropInfo <> nil end; // end if AComponent <> ni end; begin Result := True; SL := TStringList.Create; try INIF := TIniFile.Create (LngFile); // 打开语种初始化文件 try INIF.ReadSectionValues (Form.Name, SL); // 读取相应窗体信息 finally INIF.Free; end; TmpSL := TStringList.Create; try for I := 0 to SL.Count - 1 do // 分隔每一行信息 begin Split (SL.Strings[I], '=', TmpSL); Key := Trim (TmpSL.Strings[1]); CompName := Trim (Copy(Key, 1, Pos ('.', Key) - 1)); if CompName = '' then // 确定组件 AComponent := Form else AComponent := Form.FindComponent (CompName); CompProp := Trim (Copy (Key, Pos ('.', Key) 1, Length (Key))); Value := Trim (TmpSL.Strings[0]); SetPropertyValue (AComponent, CompProp, Value); // 设置属性 end; finally TmpSL.Free; end; finally SL.Free; end; end;
3、在Form显示的事件中添加代码,将目录下所有的语言文件名加入菜单项:
procedure TForm1.FormShow(Sender: TObject); var lngStrings, tmpStrings: TStrings; I: Integer; lngMenu: TMenuItem; Filename: string; IniF: TIniFile; begin lngStrings := TString.Create; try SearchLanguagePack (lngStrings); // 查找语种文件 if lngStrings.Count = 0 then // 没有找到语种文件直接退出 exit; Filename := ExtractFilePath (ParamStr (0)) 'Language' lngStrings.Strings[0] '.ini'; IniF := TIniFile.Create (Filename); Filename := IniF.ReadString('Language', ' DefaultLang ', '');// 设置为默认语种 if Filename <> '' then begin Filename := ExtractFilePath (ParamStr (0)) 'Language' Filename '.ini'; if FileExists (Filename) then begin IniF.Free; IniF := TIniFile.Create (Filename); end; end; lngMenu := TMenuItem.Create (self); lngMenu.Name := 'Language'; lngMenu.Caption := IniF.ReadString('Language', 'Language', 'Language'); MainMenu1.Items[MainMenu1.Items. Count].Add (lngMenu); // 语种菜单放到主菜单的最后 tmpStrings := TString.Create; try for I := 0 to lngStrings.Count – 1 do // 动态创建菜单项 begin lngMenu := TMenuItem.Create (self); lngMenu.Name := lngStrings.Strings[I]; // 将菜单项的名称赋予文件名 lngMenu.Caption := IniF.ReadString('Language', lngStrings.Strings[I], lngStrings.Strings[I]'); lngMenu.onClick := lngMenuClick; // 菜单事件 Language.Insert (Language.Items.Count, lngMenu); // 添加到语种菜单的最后一项上 end; finally tmpStrings.Free; end; finally lngStrings.Free; end; ChangeLanguage (Form1, IniF); // 改变界面语种 IniF.Free; end;
4、窗体中语种菜单的事件响应:
procedure TForm1.lngMenuClick (Sender: TObject); var Filename: string; begin if Sender is TMenuItem then begin // 确定语种文件,菜单项名称为语种文件名 Filename := ExtractFilePath (ParamStr (0)) 'Language' (Sender as TMenuItem).Name '.ini'; ChangeLanguage (Form1, Filename); end; end;
五、结束语
通过本次学习,让读者初步了解Delphi编程中运行时类型信息的应用技巧,同时掌握如何在程序运行时动态创建菜单。