1

在 Windows 7 中使用 C++Builder XE5 (bcc32)。

我正在尝试打开一个文件名包含宽字符的文件。我正在测试的实际文件名是C:\bΛx\foo.txt. 那里的非ASCII字符是 U+039B 。

我将此文件名正确存储在std::wstring. 但是,尝试:

std::ifstream f( filename.c_str() );

无法打开文件。

当然,在标准 C++ 中fopen只需要char *. 但是,Dinkumware C++ RTL 实现有一个重载接受wchar_t *. 不幸的是,该重载的实现...\Embarcadero\RAD Studio\12.0\source\cpprtl\Source\dinkumware\source\fiopen.cpp并没有调用_wfopen. 相反,它用于wcstombs将字符串转换为 UTF-8,然后调用fopen.

检查源代码fopen,它调用一个底层函数的窄版本___topen,最终将 UTF-8 字符串传递给CreateFile.

当我检查使用 Sysinternals Process Monitor 打开文件的尝试时,它显示它确实尝试使用 UTF-8 文件字符串打开文件,并且操作系统拒绝了这个结果NAME COLLISION

如果我使用打开文件,_wfopen( filename.c_str(), L"r" )那么一切都很好,我可以使用 CI/O 函数读取文件,但我当然不能使用 C++ iostreams。

有什么方法可以std::ifstream用来打开文件名中带有 U+039B 或其他此类字符的文件?

请注意, usingstd::wifstream 也不起作用(它仍然尝试打开文件名的 UTF-8 版本)。

4

1 回答 1

0

如果我使用打开文件,_wfopen( filename.c_str(), L"r" )那么一切都很好,我可以使用 CI/O 函数读取文件,但我当然不能使用 C++ iostreams。

我没有看到“当然”。您的问题已简化为streambufFILE*. Howard Hinnant在这里回答说,标准没有提供任何方法,但是在其streambuf上实现 - 派生类FILE*非常简单。他甚至提到了一些他认为是一个很好的起点的代码。

请注意,这只对文本文件有意义。iostreams 和二进制文件不能相处;有一个字符编码层并且ios_base::binary不会关闭它。

于 2014-10-15T21:24:10.827 回答