Как открыть std :: fstream (ofstream или ifstream) с именем файла в юникоде?
Вопрос
Вы не могли бы представить что-то столь же простое, как открытие файла с использованием стандартной библиотеки C ++ для приложения Windows было сложным делом ... но, похоже, это так. Под Unicode здесь я подразумеваю UTF-8, но я могу преобразовать в UTF-16 или что-то еще, суть в том, чтобы получить экземпляр ofstream из имени файла Unicode. Прежде чем я выберу свое собственное решение, есть ли здесь предпочтительный маршрут? Особенно кроссплатформенный?
Решение
Стандартная библиотека C ++ не поддерживает Unicode. char
и wchar_t
не обязательно должны быть кодировками Unicode.
В Windows wchar_t
- это UTF-16, но в стандартной библиотеке нет прямой поддержки имен файлов UTF-8 (тип данных char
не является Unicode в Windows) р>
В MSVC (и, следовательно, в Microsoft STL) предоставляется конструктор для файловых потоков, который принимает имя файла const wchar_t *
, позволяя вам создать поток как:
wchar_t const name[] = L"filename.txt";
std::fstream file(name);
Однако эта перегрузка не указана в стандарте C ++ 11 (она гарантирует только наличие версии на основе char
). Он также отсутствует в альтернативных реализациях STL, таких как GCC libstdc ++ для MinGW (-w64), начиная с версии g ++ 4.8.x.
Обратите внимание, что точно так же, как char
в Windows не является UTF8, в других ОС wchar_t
может не быть UTF16. Так что в целом это вряд ли будет портативным. Открытие потока с именем wchar_t
не определено в соответствии со стандартом, и указание имени файла в char
s может быть затруднено, поскольку кодировка, используемая char, варьируется в зависимости от ОС ' х годов.
Другие советы
В текущих версиях Visual C ++ std :: basic_fstream есть метод open ()
, который принимает wchar_t * в соответствии с http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx . Р>
Начиная с C ++ 17, существует кроссплатформенный способ открыть std :: fstream с именем файла Unicode, используя перегрузка std :: filesystem :: path . До C ++ 20 вы можете создать путь из строки UTF-8 с помощью станд :: файловая система :: u8path . Пример: р>
std::ofstream out(std::filesystem::u8path(u8"こんにちは"));
out << "hello";
После C ++ 20 вы можете создать путь, передав UTF-8 конструктору: std :: filesystem :: path (u8 " & # 12371; & # 12435; & # 12395; & # 12385; & # 12399; ")
(путь u8 устарел).
Используйте std :: wofstream
, std :: wifstream
и std :: wfstream
. Они принимают Unicode имя файла. Имя файла должно быть wstring
, массивом wchar_t
или оно должно иметь макрос _T ()
или префикс L
перед текстом.
Просмотрите Boost.Nowide :
#include <boost/nowide/fstream.hpp>
#include <boost/nowide/cout.hpp>
using boost::nowide::ifstream;
using boost::nowide::cout;
// #include <fstream>
// #include <iostream>
// using std::ifstream;
// using std::cout;
#include <string>
int main() {
ifstream f("UTF-8 (e.g. ß).txt");
std::string line;
std::getline(f, line);
cout << "UTF-8 content: " << line;
}
Если вы используете Qt, смешанный с std :: ifstream
:
return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));