如何在跨平台应用程序中存储偏好设置(和用户设置)?

8
我正在开发一个GUI桌面应用程序,应该在Windows、Mac OS X和Linux上本地运行。在跨平台应用程序中存储首选项的首选方法是什么?我正在使用C++,但问题(及其答案)对于任何本机编译语言都应该有效。(动态语言和Java的解决方案可以在此处查看。)
到目前为止,我的研究告诉我,至少有两种策略: (A) 使用特定于操作系统的API首选项函数。 (B) 将首选项存储在适当的(特定于操作系统的)文件夹中的文件中。
让我们考虑方法(A):我假设NSUserDefaults是Mac OS X的正确方法。在Windows系统上,我会通过RegOpenKeyEx写入注册表。但是会出现一些问题:是否有可比较且便携式的Linux API?将数据写入Windows注册表真的是未来的解决方案吗?
为了简化问题,我倾向于遵循方法(B)。因此,我只需要特定于操作系统的代码来获取适当的目录,以我选择的格式存储我的数据。在Windows上,我学习到使用SHGetFolderPath(或最近的Windows系统使用SHGetKnownFolderPath)和CSIDL_LOCAL_APPDATA是正确的方式。在Mac上,NSSearchPathForDirectoriesInDomains API调用应该可以做到相同的事情;它是一个Objective-C API,使事情变得更加复杂。最后,对于Linux版本,使用getenv("HOME")(并将getpwuid()作为备用解决方案)似乎是推荐的。
总结我的问题:
1. 是否有被认为是最佳实践的模式?
2. 是否有C++类可以抽象出所有肮脏的东西,如找到正确的文件夹?(我遇到了QSetting,但我正在使用FLTK,我不想改变我的GUI工具包。) 编辑:
“偏好设置”指的是应用程序和用户可以更改的数据,例如最近文件列表、首选窗口大小等。

使用JSON或XML。另一种选择是使用属性列表:在OS X上本地支持,在Linux和Windows上使用libplist容易处理。 - user529758
1
@H2CO3 文件存储格式不是我的问题。问题是在哪里存储这些文件? - z80crew
1
你可以将它们始终存储在与可执行文件相同的目录中,并在配置文件名前加上"."来隐藏它。这意味着用户看不到一个杂乱的目录,但很容易找到并阻止你的程序在整个文件系统中插入东西。 - James Elderfield
1
将偏好文件存储在可执行文件旁会防止应用程序更改偏好设置,至少在现代的Windows和Max OS X系统上是这样,我认为。(也许术语“偏好设置”有误导性,因此我编辑了我的问题以使我的意图更加清晰。) - z80crew
如果您将程序安装到Windows的Program Files中,则需要以管理员权限运行才能更改首选项文件,如果选择让.exe与prefs一起使用。如果这是您的计划,则将首选项放在其他地方似乎很明智。我以前使用过QStandardPaths(http://qt-project.org/doc/qt-5.0/qtcore/qstandardpaths.html),但您不必使用Qt框架的其余部分。不确定使用Qt构建会导致什么样的开销,如果有的话。 - James Elderfield
2个回答

3

由于z80crew在他的项目中使用了Fltk,我认为存储少量用户数据的最佳方式是通过Fltk Fl_Preferences类。(http://www.fltk.org/doc-1.3/classFl__Preferences.html)。

这样,您就不必担心用户数据实际存储在文件系统中的位置。您只需要创建一个由应用程序和其供应商名称标识的Fl_Preferences对象(例如,“CoolApp”和“AuthorOfCoolApp”),Fltk会将数据存储在某个地方。

在Linux下,首选项存储在~/.fltk/{vendor}/{application}.prefs中,其中{vendor}和{application}是您在Fl_Preferences构造函数中传递的相同字符串。但您不必担心这些细节。


2
+1 感谢指引 Fl_Preferences,它对于存储部分应该很有用。但我快速查看了其源代码,发现它在硬编码存储首选项的路径:sprintf(filename, "%s/Library/Preferences", fl_getenv("HOME")); 虽然苹果建议不要这样做,但似乎有很多应用程序都采用了这种方式。 - z80crew

2

我也正在开发一组跨平台插件,并且按照方法(B)所描述的做法:

  1. 使用特定于平台的代码查找正确的文件夹。
  2. 使用跨平台代码将首选项写入该文件夹。

我还想指出:

  1. 使用Windows注册表非常有限和有问题。我尽量避免使用它。
  2. 最近苹果公司推出了一首新歌:您不应直接访问 ~/Library/Preferences 文件夹,而是使用其API保存首选项值。实际上,这将首选项转换为类似于注册表的机制。我非常反感这种方法。

我不知道是否有任何库以跨平台方式实现查找当前文件夹。使用SHGetKnownFolderPath和NSSearchPathForDirectoriesInDomains,就像您所描述的那样,编写此类函数并不难。


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