简体   繁体   English

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

[英]Using ifstream when filename contains wide characters

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

I am trying to open a file whose filename contains a wide character. 我正在尝试打开一个文件名包含宽字符的文件。 The actual filename I'm testing with is C:\\bΛx\\foo.txt . 我正在测试的实际文件名是C:\\bΛx\\foo.txt The non-ASCII character there is U+039B . 那里的非ASCII字符是U + 039B。

I have this filename stored correctly in a std::wstring . 我已将此文件名正确存储在std::wstring However, trying: 但是,尝试:

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

fails to open the file. 无法打开文件。

Of course, in Standard C++ fopen only takes char * . 当然,在标准C ++中, fopen仅使用char * However, the Dinkumware C++ RTL implementation has an overload accepting wchar_t * . 但是,Dinkumware C ++ RTL实现具有接受wchar_t *的重载。 Unfortunately the implementation of that overload in ...\\Embarcadero\\RAD Studio\\12.0\\source\\cpprtl\\Source\\dinkumware\\source\\fiopen.cpp does not call _wfopen . 不幸的是,在...\\Embarcadero\\RAD Studio\\12.0\\source\\cpprtl\\Source\\dinkumware\\source\\fiopen.cpp中实现该重载不会调用_wfopen Instead it uses wcstombs to convert the string to UTF-8 and then calls fopen . 而是使用wcstombs将字符串转换为UTF-8,然后调用fopen

Checking the source for fopen , it calls the narrow version of an underlying function ___topen which ultimately passes the UTF-8 string to CreateFile . 检查源代码是否存在fopen ,它会调用基础函数___topen的窄版,该函数最终将UTF-8字符串传递给CreateFile

When I inspect the attempt to open the file using Sysinternals Process Monitor, it shows that it did attempt to open the file with a UTF-8 file string, and the operating system rejected this with the result NAME COLLISION . 当我检查使用Sysinternals Process Monitor打开文件的尝试时,它表明它确实尝试使用UTF-8文件字符串打开文件,并且操作系统拒绝了该结果,结果为NAME COLLISION

If I open the file using _wfopen( filename.c_str(), L"r" ) then all is well and I can read the file using CI/O functions, but I can't use C++ iostreams of course. 如果我使用_wfopen( filename.c_str(), L"r" )打开文件_wfopen( filename.c_str(), L"r" )那么一切都很好,我可以使用CI / O函数读取文件,但是我当然不能使用C ++ iostream。

Is there any way to use std::ifstream to open a file with U+039B or other such characters in the filename? 有什么方法可以使用std::ifstream打开带有U + 039B或文件名中其他类似字符的文件?

Note that using std::wifstream doesn't work either (it still tries to open the UTF-8 version of the filename). 请注意,使用std::wifstream也不起作用(它仍然尝试打开文件名的UTF-8版本)。

If I open the file using _wfopen( filename.c_str(), L"r" ) then all is well and I can read the file using CI/O functions, but I can't use C++ iostreams of course. 如果我使用_wfopen( filename.c_str(), L"r" )打开文件_wfopen( filename.c_str(), L"r" )那么一切都很好,我可以使用CI / O函数读取文件,但是我当然不能使用C ++ iostream。

I don't see that "of course". 我看不到“当然”。 Your problem is reduced to making an iostreams streambuf from a FILE* . 您的问题已减少到从FILE*制作iostreams streambuf Howard Hinnant answered here that there's no method provided by the Standard, but implementing a streambuf -derived class on top of FILE* is pretty straightforward. Howard Hinnant 在此处回答说,标准没有提供任何方法,但是在FILE*之上实现streambuf派生的类非常简单。 He even mentions some code that he feels would be a good starting point. 他甚至提到一些他认为是一个很好的起点的代码。

Note that this only makes sense for a text file. 请注意,这仅对文本文件有意义。 iostreams and binary files do not get along; iostream和二进制文件不相处; there's a character encoding layer and ios_base::binary does not turn that off. 有一个字符编码层, ios_base::binary不会将其关闭。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM