2013-04-09 2 views
4

У меня проблема с записью unicode в файл на C++. Я хочу записать в файл с моим собственным расширением несколько смайликов, которые вы можете получить, набрав ALT + NUMPAD (2). Я могу отобразить его на CMD, сделав символ и присвоив ему значение «\ 2», и он отобразит смайлик, но он не будет записывать его в файл.Запись Юникода в файл в C++

Вот фрагмент кода для моей программы:

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

Он будет писать в файл, но он не будет показывать то, что я хочу. Я бы показал вам, что он отображает, но StackOverflow не позволит мне отображать символ. Заранее спасибо.

+5

Вам нужно различать методы ввода и символы, а также между Unicode и различными кодировками символов (Unicode не является кодировкой). См. [Абсолютный минимум, каждый разработчик программного обеспечения, абсолютно, должен знать об Unicode и наборах символов (никаких оправданий!)] (Http://www.joelonsoftware.com/articles/Unicode.html) для праймера. – delnan

+0

Какую программу вы открываете? Скорее всего, вам нужно сначала добавить спецификации в файл, а затем записать фактические байты в файл, а не их символьные представления. – ryanbwork

+0

Я открываю его с помощью блокнота. Вся программа фактически делает файл и отображает на нем смайлики. Проект является компилятором для языка сценариев, который будет скомпилирован в специальный шестнадцатеричный код, который будет читать интерпретатор. –

ответ

4

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(); 

Оба подхода показывает смайлик в блокноте (при условии, вы используете шрифт, который поддерживает смайлики), как он читает спецификации первой, а затем декодирует Unicode соответственно элемент коды на основе этого.

3

Вы используете полную противоположность Unicode. Консоль работает с 8-битной кодовой страницей, по умолчанию на западных машинах - code page 437. Что соответствует набору символов старого символьного ПЗУ IBM PC и представляет собой кодовую страницу, ожидаемую большинством предыдущих программ DOS. Первый набор кодов символов, коды от 0 до 8 выглядеть следующим образом:

enter image description here

Примечание смайлик для кода 0x02, то тот, который вы видели на консоли. Вы можете увидеть остальные глифы в этом Wikipedia article. Отвратительная проблема с 8-битными кодировками символов заключается в том, что их так много. Блокнот читает ваш файл с помощью другой кодовой страницы. По умолчанию это Windows-1252 на машинах в Западной Европе и Америке. На этой странице нет глифов для кодов управления, поэтому вы не видите смайлик в «Блокноте».

Работа с кодовыми страницами является главной головной болью. Вот почему Unicode был изобретен.

Возможно подключение консоли к кодовой странице Юникода. Однако он должен быть 8-битной кодировкой, еще одним унаследованным от консольных программ, поддерживающих перенаправление вывода. Что делает правильный выбор utf-8. Вы можете переключиться с самой консоли, набрав chcp 65001 перед началом вашей программы. Или вы можете сделать это в своем коде, позвоните SetConsoleOutputCP(CP_UTF8);.

Еще одна неудачная деталь, о которой вы должны заботиться, вам также необходимо изменить шрифт, используемый для консоли. По умолчанию используется шрифт TERMINAL, устаревший шрифт, предназначенный для отображения глифов IBM PC, но не знает о компонентах Unicode. Используйте системное меню для переключения (нажмите Alt + Space, Properties), не так много, чтобы выбрать, но Consolas или Lucinda Console подходят.

Теперь вы можете отображать Unicode, это совсем другая история, которую представил Реми.

4

Вы должны использовать Юникод, чтобы указать символы, которые хотите отобразить.Символ, представленный байтом 02h в консоли, преобразуется кодовой страницей 437 (cp437) в символ Юникода U+263B. Использование исходного файла, сохраненного в UTF-8 с помощью спецификации, упрощает использование Unicode, поскольку вы можете вставлять или вводить нужные символы, не прибегая к escape-кодам Unicode.

Для потока файлов поток должен быть настроен для UTF-8. Есть различные способы сделать это, и это зависит от компилятора, но с использованием Visual Studio 2012, источник, сохраненную в UTF-8 Вт/BOM, и немного Googling:

#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, если смотреть в блокноте :

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

Hex дамп (правильно UTF-8):

E68891E698AFE7BE8EE59BBDE4BABAE38082E68891E58FABE9A9ACE5858BE380820D0A 

Вывести на консоль вырезать и вставить здесь. Визуальный дисплей был для каждого китайского символа без правильного шрифта, но символы отображаются правильно вставляются в SO или Блокнот.

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