2014-10-15 4 views
1

С помощью C++ Builder xe5 (bcc32) в Windows 7.Использование ifstream, когда имя файла содержит широкие символы

Я пытаюсь открыть файл, имя файла содержит широкий характер. Фактическое имя файла, с которым я тестирую, - C:\bΛx\foo.txt. Символ, не являющийся ASCII, имеет U + 039B.

У меня есть это имя файла, сохраненное правильно в std::wstring. Однако, пытается:

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

не может открыть файл.

Конечно, в стандартном C++ fopen принимает только char *. Однако реализация RTL Dinkumware C++ имеет перегрузку, принимающую 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++ iostreams, конечно.

Есть ли способ использовать std::ifstream, чтобы открыть файл с U + 039B или другими такими символами в имени файла?

Обратите внимание, что использование std::wifstream не работает (оно все еще пытается открыть версию файла UTF-8).

+0

Это явно ошибка в Dinkumware в Windows. Windows не поддерживает UTF-8 в большинстве своих API. Вы должны отправить отчет авторам Dinkumware. И версия 'wchar_t *' 'ifstream', и' wifstream', должны использовать исходное значение as-is с '_wfopen()', а не преобразовывать в UTF-8 и вызывать 'fopen()'. Это может работать на других платформах, но не на Windows. –

+1

Это было сообщено Embarcadero 2 года назад, оно все еще открыто. См. [QC# 111462] (http://qc.embarcadero.com/wc/qcmain.aspx?d=111462). –

+0

@RemyLebeau источник Dinkum имеет параметр '# ifdef', который будет делать все вызовы через' _wfopen', но (насколько я мог видеть на моем быстром просмотре) он не может заставить 'fstream (char *)' перейти к 'fopen', а также' fstream (wchar_t *) 'перейти к' _wfopen' в той же сборке. Я не уверен, поддерживает ли C++ Builder попытку перестроить свою упакованную версию Dinkum для настройки '_wfopen'? –

ответ

0

Если открыть файл с помощью _wfopen(filename.c_str(), L"r") то все хорошо, и я могу прочитать файл с помощью функций C ввода/вывода, но я не могу использовать C++ iostreams конечно.

Я не вижу этого "конечно". Ваша проблема сводится к созданию iostreams streambuf от FILE*. Ховард Хиннант ответил here, что нет стандарта, предусмотренного стандартом, но реализация класса streambuf в верхней части FILE* довольно проста. Он даже упоминает какой-то код, который, по его мнению, станет хорошей отправной точкой.

Обратите внимание, что это имеет смысл только для текстового файла. iostreams и двоичные файлы не ладят; есть слой кодирования символов, и ios_base::binary не отключает это.

+0

Да, это текстовый файл –

+0

, где я могу узнать больше о слое кодирования символов? (pre C++ 11) –

+0

Только что пришло в голову, что я могу прочитать весь файл в памяти через 'fread' или аналогичный, а затем инициализировать' sstream' с необработанными данными и пересечь пальцы –

Смежные вопросы