我想使用纯文本文件来保存用户的输入以便稍后阅读在应用程序中,可能会出现德语和西班牙语的特殊标志。不幸的是,下面的代码没有在文件中正确保存标志。如何解决这个问题最好?
我在C中的类似应用程序中通过保存.bin文件而不是.txt解决了这个问题,但在c ++中是否有更好的解决方案?
#include <string>
#include <fstream>
#include <iostream>
int main() {
std::string s = "abcöäüÑ"; //(alt + 165 for Ñ)
std::ofstream ofs{ "test.txt" };
ofs << s <<'\n'; //this works fine "abcöäüÑ"
std::string s2;
std::cin >> s2; //typeing in the app abcöäüÑ (alt+165 for Ñ)
// i use a windows system with a german keyboard setting
ofs << s2 <<'\n'; //this doesn't it gets "abc”„¥"
}
我使用带有德语键盘设置的Visual Studio 2017的Windows 7 64系统。
答案 0 :(得分:0)
最简单的解决方案(不推荐使用)是使用德语的ANSI代码页:
setlocale(LC_ALL, "gr");
cout << "abcöäüÑ\n";
ofstream fout("ansi.txt");
fout << "abcöäüÑ\n";
这适用于一些有限的字符集,如果你坚持西方拉丁字符,它是相对安全的。也许这就是你用C代码做的。它与以二进制或文本保存文件没有太大关系。
在Windows中,建议使用带有宽字符串函数的Unicode。例如:
#include <iostream>
#include <string>
#include <fstream>
#include <codecvt>
#include <io.h>
#include <fcntl.h>
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);//wcout instead of cout
_setmode(_fileno(stdin), _O_U16TEXT); //wcin instead of cin
std::locale loc_utf16(std::locale(), new std::codecvt_utf16<wchar_t>);
std::wofstream fout(L"utf16.txt", std::ios::binary);
if(fout)
{
fout.imbue(loc_utf16);
fout << L'\xFEFF'; //insert optional BOM for UTF16
fout << L"abcöäüÑ ελληνική\r\n";
fout.close();
}
std::wifstream fin(L"utf16.txt", std::ios::binary);
if(fin)
{
fin.imbue(loc_utf16);
fin.seekg(2, std::ios::beg); //skip optional BOM if it were added
std::wstring ws;
while(std::getline(fin, ws)) std::wcout << ws << std::endl;
fin.close();
}
return 0;
}
UTF16的缺点是像Linux这样的系统上的程序可能很难使用这种格式。有些人会以UTF8格式保存文件,因为UTF8更熟悉其他系统。
Windows本身是基于UTF16的。因此,您必须以UTF16读取和显示输入。但您可以以UTF8格式读/写文件。例如:
std::wcout << "enter:";
std::wstring sw;
std::wcin >> sw;
std::locale loc_utf8(std::locale(), new std::codecvt_utf8<wchar_t>);
std::wofstream fout(L"utf8.txt", std::ios::binary);
if(fout)
{
fout.imbue(loc_utf8);
fout << sw << L"\r\n";
fout << L"abcöäüÑ ελληνική\r\n";
}
这里二进制标志很重要。