2016-10-28 262 views
-4

有沒有什麼辦法可以在C++中使用環境變量作爲文件路徑? 想法是使用它們而不會消耗,所以我不需要使用wchar作爲unicode標準的語言,當我想要保存/讀取文件時。C++,使用環境變量的路徑

//編輯

很少編輯更多的解釋。

所以我試圖實現的是讀/寫文件,而不用擔心路徑中的字符。所以我不想使用wchar作爲路徑,但它應該工作,如果路徑包含一些寬字符。

有功能getenvGetEnvironmentVariable,但他們需要在Windows中設置來設置適當的語言Language for non-Unicode programsConstrol Panel - >Clock, Language, and Region - >Region and Language - >Administrative),這需要從用戶的一些行爲,這是什麼,我會盡量避免。

+0

http://en.cppreference.com/w/cpp/utility/program/getenv – UKMonkey

+0

在給我一個減號之前,請仔細閱讀我的文章。沒有擴大變量。據我所知'getenv'將環境變量轉換爲完整路徑。 – Derag

+0

如果您設置了一個環境變量,它將採用該值。如果你得到這個變量,你會得到這個值。儘管如此,如果使用'export foo =〜/ bar'之類的東西,擴展將在設置時完成 – UKMonkey

回答

1

有功能GETENV和GetEnvironmentVariable,但他們需要在Windows中設置語言恰當的語言對於非Unicode程序設置

這是專門在Windows的問題。

在其他平臺(如Linux)上,文件路徑和環境變量本身是基於字節的;您可以使用標準的C庫函數來訪問它們,這些函數採用字節串路徑,如fopen()getenv()。路徑名可能會向用戶表示Unicode字符串(使用某種編碼進行解碼,幾乎總是可以編碼任何字符的UTF-8),但對於代碼,它們只是字節串。另一方面,Windows具有本地16位(UTF-16)代碼單元的字符串的文件名和環境變量(與Unicode字符代碼點幾乎相同,但並不完全,因爲太容易了......但這是另一次的悲傷)。您可以使用UTF-16代碼單元字符串(wchar_t,在Windows上編譯時)調用Win32文件處理API,如CreateFileW()GetEnvironmentVariableW(),並直接訪問任何文件名。

還有老派傳統的基於字節的Win32功能,如GetEnvironmentVariableA()(這是GetEnvironmentVariable()指向如果您正在編譯非Unicode項目)。如果您調用這些函數,Windows必須使用某種編碼將您提供的char字節字符串轉換爲UTF-16字符串。 該編碼是「ANSI」('A')特定於語言環境的默認代碼頁,這是「非Unicode程序的語言」設置的內容。

儘管用戶可以更改該編碼,但它不能設置爲UTF-8或任何其他支持所有字符的編碼,因此即使您要求用戶更改它,仍然不會讓你訪問所有文件。因此總是要避免Win32 A API。

問題出現在您想要以適用於Windows和其他平臺的方式訪問文件時。如果您使用字節字符串調用C標準庫,則Microsoft C運行時庫會調整這些調用以調用Win32 A基於字節的API,因爲上面的API受到嚴重限制。

所以你沒有吸引力的選擇是:在你的代碼

  1. 使用wchar_tstd::wstring字符串,只使用Win32 API的與文件名和環境變量的相互作用,並接受你的代碼永遠不會在其他平臺上運行,或;
  2. 使用char和UTF-8編碼std::string字符串,並放棄在Windows上使用非ASCII字符訪問文件名和環境變量的代碼或;
  3. 寫分支#ifdef代碼來使用C標準功能的文件名和環境的交互,或者使用的Win32 API與一羣UTF-8-之間char - 到 - wchar_t字符串轉換之間進行切換的負載,從而使代碼的工作跨多個平臺,或;
  4. 使用爲您封裝(3)的庫。

這不完全是微軟的錯:Windows NT的目的是在它們的Unicode的初期UTF-8或星光層被髮明,當它被認爲是16位編碼單元串是一個完全合理的前存儲文本的方式,而不是像我們現在知道的那樣可悲的災難。但是,自從那時以來,Windows將UTF-8視爲一流公民,併爲編寫跨平臺應用程序提供了一種簡便的方法,但這一點令人非常難過。

0

標準庫提供了函數 getenv。這裏有一個例子:

#include <cstdlib> 

int main() 
{ 
    char* pPath; 
    pPath = getenv("PATH"); 
    if (pPath) 
     std::cout << "Path =" << pPath << std::endl; 
    return 0; 
}