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

type in special characters and save in file

本文关键字:存在 文件 保存 特殊字符      更新时间:2023-10-16

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

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

最简单的解决方案(已弃用(是使用德语的 ANSI 代码页:

setlocale(LC_ALL, "gr");
cout << "abcöäüÑn";
ofstream fout("answersi.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öäüÑ ελληνικήrn";
        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"rn";
    fout << L"abcöäüÑ ελληνικήrn";
}

在这里,二进制标志确实很重要。