.ini文件未创建

3

我开始使用.ini文件工作,因为我意识到与.txt文件相比,它有很多优势。无论如何,我在谷歌上搜索“Delphi inifiles”,现在正在按照Delphi About的指南进行操作。然而,即使所有语法正确,我尝试的第一行代码仍然出了问题。

Delphi About的代码:

IniFile := TIniFile.Create('myapp.ini') ;

我的代码:

IniFile := TIniFile.Create('SWEDISH_HOUSE_MAFIA.ini');

唯一的区别就是 .ini 文件本身的名称。还有,是的,我已经:
  • 在“uses”子句中声明了“IniFiles”
  • (本地) 声明了 IniFile
我将该代码放在 FormCreate 下面,但问题是运行程序时并没有创建这个 .ini 文件。有人知道问题可能是什么吗?我问了一个朋友,他说这是权限问题。
额外细节:
  • 操作系统 - Windows 7 Ultimate 64位(管理员权限)
  • 程序存储在 - 我的文档中
  • 我使用 - Delphi 2010

6
您应该彻底限定您的路径。如果您想将INI文件存储在与EXE相同的目录中,这仅在EXE位于用户目录(例如您的文档文件夹)中才可接受,那么您应该执行ExtractFilePath(Application.ExeName) + 'SWEDISH_HOUSE_MAFIA.ini' - Andreas Rejbrand
IniFile := TInifile.Create(ExtractFilePath(Application.ExeName) + 'SWEDISH_HOUSE_MAFIA.ini'); 出于某些我不知道的原因,它仍然无法正常工作。 - ple103
3
无论如何,我们必须猜测问题出在哪里,因为 - 当然 - Delphi VCL/RTL中没有错误会使得SWEDISH_HOUSE_MAFIA.ini这个文件名变得无效。你要么误诊了问题(你确定如果按照上面所示的方式重命名INI文件一切是否真的正常?),或者,也许你已经有一个名为SWEDISH_HOUSE_MAFIA.ini的文件是只读的或其他原因导致无法读取... - Andreas Rejbrand
1
@petersmileyface,你对txt文件的看法是错误的。你可以将你的组件/表单转储到一个流中,使用ObjectBinaryToText将该流转换为文本,并将其保存为Txt文件。使用这个系统比ini文件更快...因为你不必保存/重新加载每个属性...通过使用“Stored”关键字进行一些调整,你可以选择要转储或不转储的内容... - az01
4个回答

17
第一个问题是,只有在你向ini文件写入内容时才会创建该文件。我怀疑你现在没有调用WriteXXX方法之一。
另一个问题是,如果您不限定路径,那么TIniFile将尝试在Windows目录中定位它,当然您没有权限在那里写入。TIniFile所基于的底层API是已被弃用已久且表现糟糕、充满奇怪问题的私有配置文件API。相关的文档说明如下:

如果lpFileName参数不包含文件的完整路径和文件名,则WritePrivateProfileString将在Windows目录中搜索文件。 如果文件不存在,则此函数将在Windows目录中创建文件。

显然,您应该完全限定您的路径。
但是,我强烈建议您考虑使用TMemIniFile而不是TIniFile,因为TMemIniFile避免了私有配置文件API的所有缺陷。
如果您确实切换到TMemIniFile,请记得在销毁ini文件之前调用UpdateFile,因为这是将设置保存到磁盘的操作。否则,TMemIniFileTIniFile的替代品。

你知道有关于如何使用TMemIniFile的在线教程吗? - ple103
1
我也考虑过这个问题,但我没有明确提到它,因为OP声称当他使用不同的INI文件名称时,一切都完全不同,这当然是相当荒谬的。这就是为什么我在上面写了我的第二条评论,问问题是否被误诊。我认为OP会发现,即使他用稍微沉闷一点的“myapp.ini”替换黑手党启发的名称,也不会创建任何文件。 - Andreas Rejbrand
@peter 你可以像使用 TIniFile 一样使用它。据我所知,它是一个可替代的解决方案。TIniFile 存在正确性问题。我相信在其后面的私有配置API中存在着漏洞。 - David Heffernan
@Andreas 我的直觉是Peter并不是在声称一切都会因为名字不同而有所不同。我认为Peter已经拿了About代码并进行了修改。 - David Heffernan
@peter 啊,我忘记了TIniFile和TMemIniFile之间有一个区别。请看更新(这也是LU RD答案背后的原因)。 - David Heffernan
不是因为我不同意你的答案David,而是你是对的;我必须使用WriteXXX命令来创建文件。 - ple103

2
为了确保文件实际上已经保存到磁盘上,请使用:
IniFile.UpdateFile

不是这样的,你必须向文件中写入一些内容才能创建它。 - David Heffernan
@David,是的,这是不言而喻的。 :) - LU RD
不需要调用 UpdateFile。当 IniFile 被销毁时,它会自动调用。如果您不写入文件,则 UpdateFile 不会创建文件。 - David Heffernan
@David,糟糕了,自从TMemInifile被引入以来,我一直在使用它。 - LU RD
是的,如果Peter正在使用TMemIniFile,那么这几乎肯定是解释。 - David Heffernan

2
  1. 不要将ini文件保存到应用程序路径中,而是使用%APPDATA%路径。没有路径的INI文件会被创建在Windows文件夹中(Win3..XP)。在Vista/7上,这些文件会被重定向到\Users\[user]\some-magic-folder(除非您的程序以“Installer”运行)。
  2. 使用TMemFile可以大大加快操作速度。您需要调用UpdateFile/Free来更新文件,但这样做要快得多。

你确定吗?我更愿意想象它会以相同的目录作为可执行文件结束,或者如果不可能,那就在虚拟存储中。 - Andreas Rejbrand
是的,你可以尝试一下。这个功能使得Vista/7与旧的恶意应用程序兼容。在Vista/7中,普通应用程序无法写入\Windows、\Program files等目录。只有安装程序(带有漂亮的UAC对话框)才能写入。下一个级别是NTFS权限。你就是管理员也不能在那里写入。当然,你可以授予自己写入权限,但你的客户都不会这样做。 - DiGi
2
是的,我知道如果一个非特权应用程序试图写入Program Files目录、Windows目录等,则最终会将其写入每个用户的“虚拟存储”目录,这很好。但我真的不相信 TIniFile.Create('myapp.ini') 默认会在Windows文件夹(或虚拟存储的Windows文件夹)中创建文件。我认为它最终会出现在与EXE相同的目录中(或虚拟存储文件夹中)。 - Andreas Rejbrand
3
TIniFile.Create('some.ini') 是在 Windows 文件夹中创建的。初始化文件的名称。如果此参数不包含文件的完整路径,则系统将在 Windows 目录中搜索该文件。 - DiGi
2
哦,我明白了,我也遇到了异常。但是问题很简单:不要将任何配置文件存储在%appdata%之外。并且使用受限帐户在WinXP中测试应用程序... :) - DiGi
显示剩余4条评论

1
TForm1.btnWriteClick(Sender: TObject); 

var

    myINI : TINIFile;

begin 

    myINI := TINIFile.Create('Tryfolder\myini.ini');

    myINI.WriteString('Settings', 'Text Box', 'Whatever text');

    myINI.Free;

end;

就像回答3所说,你只需要将一个值写入ini文件中即可 :) 这对我来说有效(win 7 ultimate 64位)。


请注意,通过数字引用先前的答案(例如“像答案3所说的...”)并不是很有帮助,因为答案的显示顺序可能会更改(由于按投票排序和答案删除)。最好使用回答者的姓名(在其名称之前加上@以便他们被通知您已引用了他们)。 - mah

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