【问题标题】:c++ read config file parameters using GetPrivateProfileStringc++ 使用 GetPrivateProfileString 读取配置文件参数
【发布时间】:2014-09-19 08:35:29
【问题描述】:

我在 C++、Visual Studio 2012 中有一个 win32 控制台应用程序。我无法从 ini 文件中获取配置参数。我尝试了文件路径的不同可能性,例如将 .ini 文件放在源文件夹中,将完整路径写入 is,将生成的 .exe 文件放在文件夹中。执行 .exe 文件后控制台上的输出在每种情况下都是 0 或(空)字符串。我做错了什么?如何读取参数?

v1:
LPCTSTR path = L".\\config.ini";
TCHAR protocolChar[32];
int port = GetPrivateProfileString(_T("PORT"), _T("SETTINGS"), _T(""), protocolChar, 32, path);
printf("***%d***\n", port);

v2:
int port = GetPrivateProfileInt(_T("PORT"), _T("SETTINGS"), 0, _T("config.ini"));

config.ini 包含:

[SETTINGS]
USER_NUM_MAX = 256  ; Maximum number of users
PORT = 8080; 

【问题讨论】:

  • %s 打印int 将是一个问题。并且您确定该文件位于进程的当前工作目录 中?如果从 IDE 运行,您会意识到默认 CWD 是 project 文件所在的位置(vcprojx 文件),对吗?
  • 哦,因为我有不同的参数我没有在这里写正确的类型。对于 int,我使用 %d。是的,我在 ProjName.vcxproj、ProjName.vcxproj.filter、ProjName.aps、ProjName.rc 的文件夹中有 ini 文件。这样对吗?我现在将ini文件放在每个文件夹中:)。我不工作。
  • 如果它与 vcprojx 文件在同一个文件夹中,它是正确的。也许验证您甚至可以打开文件。 (std::ifstream)
  • 这是个好主意,但使用#include 无法编译。
  • 奇怪?什么样的 C++ 编译器不能 #include <fstream> ?让我猜,这段代码在一个 .c 文件中。

标签: c++ visual-studio-2012 configuration-files


【解决方案1】:

Oups,在 Windows 下点击 ini 文件并不容易。在两次尝试(v1 和 v2)中,您在 current 目录中查找文件,然后在 Windows 目录中查找文件,但不在可执行文件所在的目录中。

简单的方法是将所有ini文件放在Windows目录下。如果您发现将 ini 文件与 exe 一起保存更干净,那么您还有一些工作要做:

  • 找到可执行文件完整路径
  • exe结尾替换为ini
  • 使用该完整路径访问您的私有 ini 文件

要获取可执行文件的名称,只需使用 GetModuleFileName 和 NULL HMODULE

LPCTSTR getExecPath() {
    DWORD len = 64;
    for (;;) {
        LPTSTR fileName = new TCHAR[len];
        if (len == ::GetModuleFileName(NULL, fileName, len)) {
            delete fileName;
            len *= 2;
        }
        else {
            return fileName;
        }
    }
}

或者如果您更喜欢直接获取 ini 文件名:

LPCTSTR getIniName() {
    DWORD len = 4;
    for (;;) {
        LPTSTR fileName = new TCHAR[len];
        if (len == ::GetModuleFileName(NULL, fileName, len)) {
            delete fileName;
            len *= 2;
        }
        else {
            ::lstrcpy(fileName + lstrlen(fileName) - 3, "ini");
            return fileName;
        }
    }
}

完成后不要忘记删除文件名,因为它分配有新的...

根据评论编辑:

作为参考,windows 目录可能取决于 windows 版本。但它始终可以通过 API 函数GetWindowsDirectory 检索。摘自reference page

UINT WINAPI GetWindowsDirectory(
  _Out_  LPTSTR lpBuffer,
  _In_   UINT uSize
);

参数

  • lpBuffer [out] 指向接收路径的缓冲区的指针。此路径不以反斜杠结尾,除非 Windows 目录是根目录。例如,如果驱动器 C 上的 Windows 目录名为 Windows,则此函数检索到的 Windows 目录的路径为 C:\Windows。如果系统安装在C盘根目录下,则检索到的路径为C:。
  • uSize [in] 由 lpBuffer 参数指定的缓冲区的最大大小,以 TCHAR 为单位。该值应设置为 MAX_PATH。

返回值

如果函数成功,则返回值是复制到缓冲区的字符串长度,以 TCHAR 为单位,不包括终止空字符。

如果长度大于缓冲区大小,则返回值是保存路径所需的缓冲区大小。

如果函数失败,返回值为零。要获取扩展错误信息,请调用 GetLastError。 *

【讨论】:

  • 你的意思是这个句子(简单的方法是将所有ini文件放在Windows目录下。如果你发现更干净......)有两种可能性?还是我必须做这三个步骤?我的 ProjectName.exe 文件位于文件夹 ProjectName->Debug 中。是这个可执行文件吗,什么意思?
  • @Alexito:是的,您有两种可能性:要么将 ini 文件放在 Windows 目录中并将其命名为 T"config.ini",要么将其放在与可执行文件相同的目录中并使用完整路径作为在我的回答中描述。参考:GetPrivateProfileString 函数的文档 lpFileName 初始化文件的名称。如果此参数不包含文件的完整路径,则系统在 Windows 目录中搜索该文件。
  • 如何找到windows目录?我试了一些,但找不到。
  • @Alexito : 使用参考资料编辑帖子以查找 Windows 目录。
  • 谢谢!输出只是 C。在我将 config.ini 放入其中之后。它不读取参数。我再次尝试了不同的变体,如上面介绍的 v1、v2、“config.ini”、“.\\config.ini”等。可能是什么问题?
【解决方案2】:

我从 VS2010 更新到 VS2012 时遇到了这个问题。

在 VS 2010 上,我只是使用 .ini 文件的文件名作为 lpFileName (see MSDN Documentation) 的参数调用函数。

这不再适用于 VS 2012,所以我改为使用这样的完整路径:

char directoryPath[MAX_PATH];
char readParameter[MAX_STR_LEN];

GetCurrentDirectory( directoryPath, MAX_PATH );

string directoryPathAsString(directoryPath);
directoryPathAsString = directoryPathAsString + "\\" + filename;

GetPrivateProfileString("section","parameter","0",readParameter,MAX_STR_LEN, directoryPathAsString.c_str());

【讨论】:

    猜你喜欢
    • 2011-10-28
    • 2014-04-04
    • 2013-10-12
    • 1970-01-01
    • 2011-05-30
    • 2023-04-01
    • 2014-09-21
    • 1970-01-01
    • 2012-04-28
    相关资源
    最近更新 更多