输入特殊字符并保存在文件中

时间:2018-04-18 19:17:05

标签: c++ windows visual-c++ unicode

我想使用纯文本文件来保存用户的输入以便稍后阅读在应用程序中,可能会出现德语和西班牙语的特殊标志。不幸的是,下面的代码没有在文件中正确保存标志。如何解决这个问题最好?

我在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系统。

1 个答案:

答案 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";
}

这里二进制标志很重要。