文件名包含宽字符时使用ifstream

时间:2014-10-15 21:16:23

标签: c++ windows unicode ifstream c++builder-xe5

在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版本)。

1 个答案:

答案 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不会关闭它。