使用C ++将Unicode写入文件

时间:2013-04-09 19:47:00

标签: c++ unicode ofstream writetofile

我在使用C ++将unicode写入文件时遇到问题。我想写一个带有我自己的扩展名的文件,你可以通过键入ALT + NUMPAD(2)来获得一些笑脸。我可以通过制作一个字符并在其上分配'\ 2'的值来在CMD上显示它,它将显示一个笑脸,但它不会将其写入文件。

以下是我的程序代码片段:

ofstream myfile;
myfile.open("C:\Users\My Username\test.exampleCodeFile");
myfile << "\2";
myfile.close();

它将写入文件,但它不会显示我想要的内容。我会告诉你它显示什么,但StackOverflow不会让我显示角色。提前谢谢。

3 个答案:

答案 0 :(得分:5)

ALT + NUMPAD2与ASCII字符2不同,这是您的代码写入文件的内容。 ALT代码是DOS处理非ASCII字符的方式。 CMD.COM为ALT + NUMPAD2显示的字形实际上是Unicode代码点U + 263B“BLACK SMILING FACE”。作为Unicode字符,您最好使用UTF-8或UTF-16对文件进行编码,例如:

ofstream myfile;
myfile.open("C:\\Users\My Username\\test.txt");
myfile << "\xEF\xBB\xBF"; // UTF-8 BOM
myfile << "\xE2\x98\xBB"; // U+263B
myfile.close();

ofstream myfile;
myfile.open("C:\\Users\\My Username\\test.txt");
myfile << "\xFF\xFE"; // UTF-16 BOM
myfile << "\x3B\x26"; // U+263B
myfile.close();

这两种方法在记事本中显示笑脸(假设您使用支持表情符号的字体),因为它首先读取BOM,然后根据该值解码Unicode码点。

答案 1 :(得分:4)

您必须使用Unicode指定要显示的字符。控制台中由字节02h表示的字符由代码页437(cp437)转换为Unicode字符U+263B。使用带有BOM的UTF-8保存的源文件可以更容易地使用Unicode,因为您可以粘贴或键入所需的字符,而无需使用Unicode转义码。

对于文件流,需要为UTF-8配置流。有多种方法可以做到这一点,它取决于编译器,但使用Visual Studio 2012,源代码保存为UTF-8 w / BOM,以及一些谷歌搜索:

#include <locale>
#include <codecvt>
#include <fstream>
#include <iostream>
#include <io.h>
#include <fcntl.h>
using namespace std;

int main()
{
    const std::locale utf8_locale = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>());
    wofstream f(L"sample.txt");
    f.imbue(utf8_locale);
    f << L"\u263b我是美国人。我叫马克。" << endl;

    _setmode(_fileno(stdout),_O_U16TEXT);
    wcout << L"\u263b我是美国人。我叫马克。" << endl;
}

在记事本中查看的sample.txt内容:

☻我是美国人。我叫马克。

十六进制转储(正确的UTF-8):

E68891E698AFE7BE8EE59BBDE4BABAE38082E68891E58FABE9A9ACE5858BE380820D0A

输出到控制台剪切并粘贴在此处。对于没有正确字体的每个汉字,视觉显示为 ,但字符显示正确粘贴到SO或记事本中。

☻我是美国人。我叫马克。

答案 2 :(得分:3)

您正在使用与Unicode完全相反的方法。控制台使用8位代码页运行,西方机器上的默认代码页为code page 437。它与旧的IBM PC字符ROM的字符集匹配,是大多数传统DOS程序所期望的代码页。第一组字符代码,代码0到8如下所示:

enter image description here

请注意您在控制台上看到的代码0x02的笑脸。您可以在此Wikipedia article中看到其余的字形。 8位字符编码的一个令人讨厌的问题是它们中有这么多。记事本使用不同的代码页读取您的文件。默认情况下,在西欧和美洲的机器上为Windows-1252。该页面没有控制代码的任何字形,这就是为什么你没有在记事本中看到笑脸。

处理代码页是一个令人头痛的问题。这就是为什么发明Unicode的原因。

可以将控制台切换到Unicode代码页。然而,它必须仍然是一个8位编码,这是支持输出重定向的控制台程序的另一个遗留问题。这是正确的选择utf-8。您可以在启动程序之前键入chcp 65001来从控制台本身切换。或者您可以在代码中执行此操作,请致电SetConsoleOutputCP(CP_UTF8);

您需要注意的另一个不幸的细节,您还需要更改用于控制台的字体。默认字体是TERMINAL,这是一种遗留字体,旨在显示IBM PC字形,但不知道有关Unicode的bean。使用系统菜单切换(按Alt + Space,属性),选择不多,但Consolas或Lucinda控制台是合适的。

现在你可以显示Unicode,这是Remy介绍的另一个故事。