2016-10-28 231 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; 
}