在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" )
打开文件,那么一切都很好,我可以使用C I / O函数读取文件,但我当然不能使用C ++ iostream。
有没有办法使用std::ifstream
打开U + 039B文件或文件名中的其他此类字符?
请注意,使用std::wifstream
也不起作用(它仍尝试打开文件名的UTF-8版本)。
答案 0 :(得分:0)
如果我使用
_wfopen( filename.c_str(), L"r" )
打开文件,那么一切都很好,我可以使用C I / O函数读取文件,但我当然不能使用C ++ iostream。
我当然没有看到"当然"。您的问题已缩减为从streambuf
制作iostream FILE*
。 Howard Hinnant回答here标准没有提供任何方法,但在streambuf
之上实现FILE*
派生类是非常简单的。他甚至提到了一些他认为是一个很好的起点的代码。
请注意,这仅对文本文件有意义。 iostream和二进制文件不相处;这是一个字符编码图层,ios_base::binary
不会关闭它。