Мне нужно использовать программу на C ++ для создания нового файла с символами Unicode (например, äöüé.txt
) в Windows и Linux со следующим кодом:
int main(){
std::string nameOfFile;
std::cout << "Please enter the name of file ! " << std::endl;
std::cin >> nameOfFile;
std::cout << "name = " << nameOfFile << std::endl;
std::fstream mystream;
mystream.open(nameOfFile, std::ios::out | std::ios::trunc | std::ios::binary);
mystream.close();
return 0;
}
I выполнить одну и ту же программу в Windows и Linux (с Visual Studio 2015 для Windows и g cc 5.4 для Linux), с вводом "äöüé.txt"
в терминале.
Я обнаружил, что файл "äöüé.txt"
создан правильно с правильным именем файла "äöüé.txt"
в Linux. Но имя файла, созданное в Windows, кажется неправильным ("„”‚.txt"
).
Я знаю, что это из-за разницы в кодировке между Linux и Windows. Linux принимает UTF-8, а Windows принимает UTF-16.
Теперь мне нужно правильно создать файл в Windows, как и в Linux.
I пробовал следующие методы:
(1) в соответствии с std :: wstring VS std :: string , я пытался использовать функцию MultiByteToWideChar()
от Microsoft, как подробно описано здесь: Откройте файл с кодировкой utf8 в c ++ Windows, но FAIL:
#ifdef _MSC_VER
std::wstring ToUtf16(std::string str)
{
std::wstring ret;
int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
if (len > 0)
{
ret.resize(len);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &ret[0], len);
}
return ret;
}
#endif
int main()
{
std::string nameOfFile;
std::cout << "Please enter the name of file ! " << std::endl;
std::cin >> nameOfFile;
std::cout << "name = " << nameOfFile << std::endl;
std::ifstream iFileStream(
#ifdef _MSC_VER
ToUtf16(nameOfFile).c_str()
#else
nameOfFile.c_str()
#endif
, std::ifstream::in | std::ifstream::binary);
return 0;
}
(2) в соответствии с Как создать файл с UNICODE-путем на Windows с C ++ , Я пытался использовать функцию CreateFile()
, но FAIL:
int main()
{
std::string nameOfFile;
std::cout << "Please enter the name of file ! " << std::endl;
std::cin >> nameOfFile;
std::cout << "name = " << nameOfFile << std::endl;
/*convert string to char array */
int stringLen = nameOfFile.length();
char* text = new char[stringLen + 1];
std::strcpy(text, nameOfFile.c_str());
/*Convert to utf-16*/
HANDLE hFile = CreateFileA(nameOfFile.c_str(),
GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE) {
int file_descriptor = _open_osfhandle((intptr_t)hFile, 0);
if (file_descriptor != -1) {
FILE* file = _fdopen(file_descriptor, "w");
if (file != NULL) {
std::ofstream stream(file);
stream << "Hello World\n";
// Closes stream, file, file_descriptor, and file_handle.
stream.close();
file = NULL;
file_descriptor = -1;
hFile = INVALID_HANDLE_VALUE;
}
}
}
return 0;
}
(3) в соответствии с https://en.cppreference.com/w/cpp/locale/codecvt_utf8_utf16 (см. Пример внизу), я пытался использовать codecvt
, а затем используйте _wfopen()
, как описано здесь: https://docs.microsoft.com/en-us/previous-versions/yeby3zcb (v% 3Dvs.140) , но FAIL.
Мои ограничения таковы:
C ++ 11 (я знаю, что C ++ 17 включает файловую систему в STL, поэтому эту проблему можно решить), как описано здесь: Как открыть std :: fstream (ofstream или ifstream) с именем файла в юникоде?
повышение не разрешено
Библиотека QT не разрешена
Единственное, что я могу использовать, это стандартная библиотека C ++ и библиотека Microsoft.
У вас есть идеи?
Алану:
Благодаря вашему ответу я использовал следующий код для проверки кодировки символов в моем windows:
int main(){
std::wstring nameOfFile;
std::wcout << "Please enter the name of file ! " << std::endl;
std::wcin >> nameOfFile;
std::wcout << "name = " << nameOfFile << std::endl;
/*convert string to char array */
int stringLen = nameOfFile.length();
wchar_t* text = new wchar_t[stringLen + 1];
std::wcscpy(text, nameOfFile.c_str());
/*Get the coding number*/
std::cout << "strlen(text) : " << wcslen(text) << std::endl;
std::cout << "text(ordinals) :";
for (size_t i = 0, iMax = wcslen(text); i < iMax; ++i)
{
std::cout << " " << static_cast<unsigned int>(
static_cast<unsigned char>(text[i])
);
}
_wfopen(text, L"w");
return 0;
}
Кодовая страница моего Windows равна 850, и на выходе видно, что äöüé
кодируется как 132 148 129 130
, что, согласно таблице для кода страница 850 точно соответствует ä(132) ö'(148) ü(129) é(130)
.
. В конце кода выше я использую функцию _wfopen()
для создания файла, но точный созданный файл все еще имеет неправильное имя.
Кстати, использование std::fstream()
, как показано в моем втором примере, не может создать новый файл, оно может просто прочитать существующий файл.
Я думаю, fopen()
или _wfopen()
являются единственными функциями, которые могут создавать новый файл вместо чтения существующего файла.