ini文件在Win32系统中还有一定的用武之地,起码现在还没被XML全部剿灭,毕竟对简单的信息保存如登陆用户记忆等还是要比XMl简洁的多有
效的多了。ini文件本身是文本文件,只是限定了特定格式表示特定形式的数据罢了。
成也文本,败也文本,最近在开发中使用Ini文件保存了敏感信息,必须涉及字符串加密了,仅对信息串加密,用户可以看到ini文件的清晰结
构,似乎感觉不怎么安全,文件级加密似乎又显罗索需要讲文件折腾来折腾去,何不看看Delphi中TIniFile是如何实现的。
追踪TIniFile,发现竟又两种实现,原来Delphi是将windows和LINUX分开实现。
{$IFDEF MSWINDOWS}
{ TIniFile - Encapsulates the Windows INI file interface
(Get/SetPrivateProfileXXX functions) }
TIniFile = class(TCustomIniFile)
public
............
{$ELSE}
TIniFile = class(TMemIniFile)
public
destructor Destroy; override;
end;
{$ENDIF}
windows下的实现是借用了API完成的,这当然是最好的了,效率不说,起码将容性不会又问题,但对解决我们的问题可就没有门路了。而且Windows下还继承了TCustomIniFile类,看看TCustomIniFile里面是大量的虚方法,除了create方法中记录了文件名外,没有关键方法,基本是接口了。
看LINUX实现,继承自TMemIniFile,只覆盖了一个方法Destroy,对该方法待会再回来圈点。查看TMemIniFile类,可以看到它也继承自TCustomIniFile,两种实现在这里走到一起,TCustomIniFile中得虚方法在TMemIniFile里都有了实现,从create方法入手,
constructor TMemIniFile.Create(const FileName: string);
begin
inherited Create(FileName);
FSections := THashedStringList.Create;
{$IFDEF LINUX}
FSections.CaseSensitive := True;
{$ENDIF}
LoadValues;
end;
这里调用了LoadValues,它应该是读取文件的地方,果然,近去后发现了
List := TStringList.Create;
try
List.LoadFromFile(FileName);
SetStrings(List);
文件读取后被放入了 TStringList对象中,我们应该在这里有机会做文本的解密动作,但不幸的是
LoadValues方法是private的,不过数据加载后又有SetStrings方法,该方法是public,覆盖该方法,加入对list串的解密就OK.其他的不管,看看加密能在哪里完成。类中没有明显的SaveXX的方法,不过没关系,既然是用TstringList的LoadFromFile方法读的数据,也应该对应用其savetoFile方法保存吧,查找 savetoFile方法,果然在UpdateFile中,是public方法,其中还调用了GetStrings 方法,功能和SetStrings方法对应,也是public方法,说来LoadValues和UpdateFile也是功能对应方法了,为什么要一个私有一个公开,没想明白。 好了加密也有地方了,就对应放在SetStrings中好了。 剩下的就是找一对字符串加密解密的方法,这个到处都有了,根据自己需要吧。
回头刚才说了LINUX实现中只覆盖了一个Destroy,里面是对象释放前调用了一下了UpdateFile方法用作保存文件,也许这个动作的差别才能体现TMemIniFile的意义了。给我们的提示就是我继承自
操作很简单了:
做一个自己的类,继承TMemIniFile方法,覆盖 SetStrings 方法,增加字符串解密功能,覆盖SetStrings方法,增加加密功能,覆盖Destroy方法,增加UpdateFile调用,OK。
多想一点,在UpdateFile方法中,不管是否对ini内容进行修改,该方法都要将ini内容重新生成,并重新保存到文件,如果ini内容比较多,本身内容生成、加密过程都和保存文件过程都比较费时间,如果只是读ini中内容,实在没必要浪费这样的操作,实现也很简单,设置一个读写标志,覆盖DeleteKey、EraseSection、WriteString三个方法,在其中设置一下读写标志,覆盖UpdateFile方法,其中判断如果没有内容改动,就什么也不做,直接退出就跳过三个费时的操作了。