16200 发表于 2023-11-27 16:47

C++ 一个SQL连接附加数据库读取本地配置文件问题

具体实现 是运行代码后, 自动连接SQLSERVER 这一步已经实现了,,, 然后就是附加MDF数据库   读取本地 配置文件下名称 路径=D:\\Mud2   数据库实际是在D:\\Mud2\\Data 这个目录下由于 Data是固定得 所以我想把前面路径设置可修改的 后面采用拼接DATA 起来, 但是不管怎么设置都是找不到。 搞不明白到底是问题出在哪里。 有大神帮我看看这串代码吗?
CONFIG 配置文件内容
路径=D:\\Mud2
计算机名称=DESKTOP-5A5123EW
SQLserver_user=SA
SQLserver=111114123asdqwe


#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <locale>

int main() {
    SQLHANDLE henv; // Environment
    SQLHANDLE hdbc; // Connection
    SQLRETURN retcode;
    // Allocate environment handle
    SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
    SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);

    std::locale::global(std::locale("")); // 设置全局区域设置

    // Read configuration from file
    std::wifstream configFile("config.txt"); // 使用wifstream读取宽字符
    if (!configFile.is_open()) {
      std::wcout << L"无法打开配置文件" << std::endl;
      return 1;
    }

    std::wstring computerName, sqlServerUser, sqlServerPassword, dataPath;
    std::wstring line;
    while (std::getline(configFile, line)) {
      if (line.find(L"计算机名称=") != std::wstring::npos) {
            computerName = line.substr(line.find(L"=") + 1);
      }
      else if (line.find(L"SQLserver_user=") != std::wstring::npos) {
            sqlServerUser = line.substr(line.find(L"=") + 1);
      }
      else if (line.find(L"SQLserver=") != std::wstring::npos) {
            sqlServerPassword = line.substr(line.find(L"=") + 1);
      }
      else if (line.find(L"路径=") != std::wstring::npos) {
            dataPath = line.substr(line.find(L"=") + 1);
            dataPath + L"\\Data\\"; // 确保路径末尾有分隔符
      }
    }
    configFile.close();

    // Allocate connection handle
    SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);

    // Connect to the SQL Server
    std::wstring connectionString = L"DRIVER={SQL Server};SERVER=" + std::wstring(computerName.begin(), computerName.end())
      + L";DATABASE=master;UID=" + std::wstring(sqlServerUser.begin(), sqlServerUser.end())
      + L";PWD=" + std::wstring(sqlServerPassword.begin(), sqlServerPassword.end());
    retcode = SQLDriverConnect(hdbc, NULL, (SQLWCHAR*)connectionString.c_str(), SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);

    if (SQL_SUCCEEDED(retcode)) {
      std::cout << "成功连接到 SQL Server" << std::endl;

      // Attach MDF data files
      std::vector<std::wstring> mdfFiles = { L"Account", L"Game", L"Manage", L"Res" };
      SQLHANDLE hstmt;// Statement
      for (const auto& mdf : mdfFiles) {
            std::wstring mdfFilePath = std::wstring(dataPath.begin(), dataPath.end()) + L"\\" + mdf + L".mdf";
            std::wstring databaseName = mdf;

            retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);// Allocate statement handle
            if (SQL_SUCCEEDED(retcode)) {
                std::wstring attachQuery = L"CREATE DATABASE " + databaseName + L" ON (FILENAME = '" + mdfFilePath + L"') FOR ATTACH";

                retcode = SQLExecDirect(hstmt, (SQLWCHAR*)attachQuery.c_str(), SQL_NTS);

                if (SQL_SUCCEEDED(retcode)) {
                  std::wcout << L"MDF 数据文件 " << mdfFilePath << L" 成功附加为数据库 " << databaseName << std::endl;
                }
                else {
                  SQLWCHAR sqlState, errMsg;
                  SQLINTEGER nativeError;
                  SQLSMALLINT textLength;

                  SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, 1, sqlState, &nativeError, errMsg, SQL_MAX_MESSAGE_LENGTH, &textLength);
                  std::wcout << L"无法附加 MDF 数据文件 " << mdfFilePath << L" 为数据库 " << databaseName << std::endl;
                  std::wcout << L"错误信息:" << errMsg << std::endl;
                }

                SQLFreeHandle(SQL_HANDLE_STMT, hstmt);// Free statement handle
            }
      }
    }
    else {
      std::cout << "无法连接到 SQL Server" << std::endl;
    }

    // Disconnect and free handles
    SQLDisconnect(hdbc);
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);

    return 0;
}

jyjjf 发表于 2023-11-27 16:58

运行管理员权限问题?

16200 发表于 2023-11-27 17:00

jyjjf 发表于 2023-11-27 16:58
运行管理员权限问题?

我也是用管理员权限运行了

史前小虫 发表于 2023-11-27 17:06

else if (line.find(L"路径=") != std::wstring::npos) {
    dataPath = line.substr(line.find(L"=") + 1);
    dataPath + L"\\Data\\"; // 确保路径末尾有分隔符
}
将 L"\\Data\\" 拼接到 dataPath,但实际上这行代码并没有改变 dataPath 的值,
因为 dataPath + L"\\Data\\"; 这个表达式计算出来的新字符串并没有被赋值给任何变量。
dataPath = dataPath + L"\\Data\\";或者dataPath += L"\\Data\\";

Eaglecad 发表于 2023-11-27 17:22

代码问题;dataPath + L"\\Data\\"; // 确保路径末尾有分隔符 这句 少了等号 应该是 dataPath += L"\\Data\\"; // 确保路径末尾有分隔符

vscos 发表于 2023-11-27 18:53

配置文件里的目录符不能用\\这样的双斜扛,改单个看看

16200 发表于 2023-11-27 22:02

Eaglecad 发表于 2023-11-27 17:22
代码问题;dataPath + L"\\Data\\"; // 确保路径末尾有分隔符 这句 少了等号 应该是 dataPath += L"\\Dat ...

按照这个改 也是读取不到。 如果用绝对路径 就可以读取到。。。

16200 发表于 2023-11-27 22:03

史前小虫 发表于 2023-11-27 17:06
else if (line.find(L"路径=") != std::wstring::npos) {
    dataPath = line.substr(line.find(L"=") +...

两种方式我都试了,也是读取不到。如果是因为 管理员权限会读取到文件 然后返回 拒绝5 是没权限。 这个是直接读取不到路径

Eaglecad 发表于 2023-11-27 23:02

我按你上面写的,就改了那一处,是可以读取到结果的。你那还不行,可能是以下几个原因
1.配置文件路径问题,比如运行程序在debug目录,配置文件在源代码目录。
2.配置文件,编码格式与开发环境编码格式不一致问题。文件流是宽字节,配置文件最好是gbk
3.读取配置非当前所示文件内容。

16200 发表于 2023-11-28 11:43

Eaglecad 发表于 2023-11-27 23:02
我按你上面写的,就改了那一处,是可以读取到结果的。你那还不行,可能是以下几个原因
1.配置文件路径问题 ...

好的。谢谢 是编码问题
页: [1]
查看完整版本: C++ 一个SQL连接附加数据库读取本地配置文件问题