У меня есть кросс-платформенный код, и он должен использовать какой-то файл конфигурации. Все работает нормально, кроме случая, когда путь к имени файла конфигурации содержит символы, отличные от ANSI.
Для открытия / чтения файла использую std::ifstream.
На платформе Windows (MSVC) решением является использование перегруженной версии std::ifstream, которая может принимать имя пути как wchar_t*, поэтому имя пути закодировано как utf16, и нет проблем с национальными символами в пути.
Но какое решение для систем NIX *?
Насколько мне известно, все имена таких файлов закодированы с помощью UTF-8, и можно использовать char* в качестве указателя на строку.
Например:
std::string path_name = ...; //assigning path name
std::ifstream fin(path_name.c_str());
Но как насчет c_str(), который возвращает постоянный указатель на строку имени файла, за которой следует терминатор null? Поскольку последовательность байтов UTF-8 может содержать нули как часть кодовых точек, такая строка может быть усечена.
Так что, пожалуйста, укажите мне, где я ошибаюсь, или предложите какое-нибудь портативное решение, если я в порядке))
Спасибо.
UTF-8 не содержит нулей как часть кодовых точек. Текст UTF-8 заканчивается нулем, как текст ASCII.
Не могли бы вы пояснить, что вы имеете в виду под "Все работает нормально, кроме случая, когда путь к имени файла конфигурации содержит символы, отличные от ANSI."? А почему вы думаете, что проблема в строке имени файла?
@ ÖöTiib UTF-8 должен использовать до четырех байтов на символ. Каждый байт многобайтовой последовательности содержит самый старший бит как 1. Итак, да, вы абсолютно правы - где нет нулевого байта в такой необработанной строке utf-8. Вот в чем я ошибался. Спасибо. Как я могу отметить ваш комментарий как ответ?
@NeilButterworth Позор мне. Я застрял на C++ 98) Начиная с C++ 11, где это std :: string версия конструктора std :: ifstream.
Вы можете ответь на свой вопрос.
@ user1503944 UTF-8 supposed to use up to four bytes, per symbol. Не условное обозначение. Вы, наверное, думаете о кодовая точка. Символ может состоять из одной или нескольких кодовых точек (каждая из которых состоит из четырех кодовых единиц в UTF-8).





UTF-8 не содержит нулей как часть кодовых единиц. Байты в многобайтовых последовательностях должны иметь самый старший бит. Таким образом, текст UTF-8 может оканчиваться нулем, как текст ASCII.
Поэтому вы можете использовать path_name.c_str() в качестве имени файла в кодировке UTF-8.
Байты в строке UTF-8 известны как Единицы кода. Кодовые точки - это значения Unicode, которые UTF кодируют в кодовые единицы. В любом случае в UTF-8 есть нулевой байт - символ NUL, кодовая точка Unicode U+0000, которая закодирована в UTF-8 как байт 0x00 и, таким образом, может использоваться в качестве нулевого терминатора в строке с завершающим нулем.
ifstream имеет конструктор, который принимает в качестве параметра std :: string - нет необходимости использовать c_str ().