SQLite3 預設 API 僅接受 UTF-8 編碼的檔案路徑。當資料庫檔案置於包含中文的目錄 (如 C:\我的資料\db.sqlite) 時,直接傳入 ANSI/MBCS 路徑會導致 sqlite3_open 失敗 (返回 SQLITE_CANTOPEN)。解決關鍵:**將路徑轉為 UTF-8 再呼叫 API**。
// 錯誤示範:中文路徑直接傳入
sqlite3_open("C:\\我的資料\\db.sqlite", &db); // 失敗
char szFileNameUtf8[MAX_PATH * 4]; // UTF-8 可能較長,預留 4 倍空間
_bstr_t bstrFileName = strPath; // strPath 為 CString/TCHAR* 原始路徑
if (HasChineseChar(strPath)) // 簡易判斷是否含中文 (或直接全部轉換)
{
// ATL 提供 Unicode → UTF-8 轉換
AtlUnicodeToUTF8(bstrFileName, bstrFileName.length(), szFileNameUtf8, sizeof(szFileNameUtf8));
result = sqlite3_open(szFileNameUtf8, &m_sqlite3DB);
}
else
{
// 純 ASCII 路徑可直接使用
result = sqlite3_open(strPath, &m_sqlite3DB);
}
if (result == SQLITE_OK)
{
char *errmsg = NULL;
int nError = sqlite3_exec(m_sqlite3DB,
"CREATE TABLE Table_a( ID INTEGER PRIMARY KEY AUTOINCREMENT, name NVARCHAR(32) )",
NULL, NULL, &errmsg);
if (nError != SQLITE_OK)
{
ATLTRACE("建立資料表失敗,錯誤碼:%d,原因:%s\n", nError, errmsg);
sqlite3_free(errmsg);
}
}
bool HasChineseChar(const CString& str)
{
for (int i = 0; i < str.GetLength(); ++i)
{
// 簡易判斷:雙位元組字元 (中文 Big5/GBK 皆大於 0x80)
if (static_cast(str[i]) > 0x80) return true;
}
return false;
}
std::filesystem::path:原生支援 Unicode,配合 sqlite3_open16 (接受 UTF-16) 最簡潔WideCharToMultiByte(CP_UTF8, ...):無 ATL 依賴的通用做法sqlite3_open16 直接接受 UTF-16 (Windows wchar_t*),可完全避開轉碼麻煩MAX_PATH (260),建議使用延長路徑前綴 \\\\?\\ 或動態配置緩衝區一行 AtlUnicodeToUTF8 (或 WideCharToMultiByte),徹底解決 SQLite3 中文路徑難題,讓資料庫部署不再受限於目錄命名習慣。