Я попробовал несколько опций, и я обосновываюсь на MVVM как лучший выбор для меня. Смешиваемость является важным моментом, и я также нахожу аспект VM интуитивным для оснащения динамических поведений и процедурных эффектов и анимаций (как Silverlight Nikhil. FX). Однажды я старался избегать Смешения в целом через быстрые интерфейсы, но нахожу связь между UI и поведением слишком болезненной в конечном счете. Я хочу разработать свой UI в Смешении и затем добавить эффекты и другие поведения в коде, это оказывается лучшим шаблоном для меня для следования до сих пор.
Модель, используемая C ++ для кодировок, унаследована от C и восходит как минимум к 1989 году.
Два основных момента:
Итак, чтобы получить что-либо, вы должны установить локаль.
Если я использую простую программу
#include <locale>
#include <fstream>
#include <ostream>
#include <iostream>
int main()
{
wchar_t c = 0x00FF;
std::locale::global(std::locale(""));
std::wofstream os("test.dat");
os << c << std::endl;
if (!os) {
std::cout << "Output failed\n";
}
}
], которые используют языковой стандарт среды и выводят в файл широкий символ кода 0x00FF. Если я прошу использовать языковой стандарт «C», я получаю
$ env LC_ALL=C ./a.out
Output failed
, что языковой стандарт не может обрабатывать широкий символ, и мы получаем уведомление о проблеме, поскольку сбой ввода-вывода.
Очень частичный ответ на первый вопрос: файл представляет собой последовательность байтов, поэтому при работе с wchar_t
по крайней мере должно произойти некоторое преобразование между wchar_t
и char
. Выполнение этого преобразования «разумно» требует знания кодировок символов, поэтому этому преобразованию разрешено быть зависимым от локали на основании использования фасета в локали потока.
Тогда возникает вопрос, как это преобразование должно быть быть изготовленным в единственной локали, требуемой стандартом: «классической». На этот вопрос нет "правильного" ответа, и поэтому в стандарте это очень расплывчато. Из вашего вопроса я понимаю, что вы предполагаете, что слепое приведение (или memcpy () - ing) между wchar_t [] и char [] было бы хорошим способом. Это небезосновательно, и на самом деле это то, что (или, по крайней мере, было) сделано в некоторых реализациях.
Другая точка зрения будет заключаться в том, что, поскольку codecvt является аспектом локали, разумно ожидать, что преобразование выполняется с использованием «кодировка локали» (я здесь не совсем точен, так как концепция довольно расплывчата). Например, можно было бы ожидать, что турецкая локаль будет использовать ISO-8859-9, а японская - использовать Shift JIS. По сходству «классический» языковой стандарт будет преобразован в эту «кодировку языкового стандарта». По-видимому, Microsoft предпочла просто обрезать (что приводит к IS-8859-1, если мы предположим, что wchar_t
представляет UTF-16 и что мы остаемся в базовой многоязычной плоскости), в то время как реализация Linux, о которой я знаю, решила придерживаться ASCII.
По вашему второму вопросу:
Кроме того, получим ли мы настоящие потоки Unicode с C ++ 0x или я что-то здесь упускаю?
В [ locale.codecvt] в n2857 (последний черновик C ++ 0x, который у меня есть), можно прочитать:
Специализация
codecvt
преобразуется между UTF-16 и схемы кодирования UTF-8, а специализацияcodecvt
преобразует схемы кодирования UTF-32 и UTF-8.codecvt
преобразует собственные наборы символов для узких и широких символов.
В разделе [locale.stdcvt] мы находим:
Для аспекта
codecvt_utf8
:По вашему второму вопросу:
Кроме того, получим ли мы настоящие потоки Unicode с C ++ 0x или мне здесь чего-то не хватает?
В разделе [locale.codecvt] n2857 (последняя версия C + + 0x draft, что у меня под рукой) можно прочитать:
Специализация
codecvt
преобразует схемы кодирования UTF-16 и UTF-8, а также специализациюcodecvt
выполняет преобразование между схемами кодирования UTF-32 и UTF-8.codecvt
преобразует собственные наборы символов для узких и широких символов.В разделе [locale.stdcvt] мы находим:
Для аспекта
codecvt_utf8
:По вашему второму вопросу:
Кроме того, получим ли мы настоящие потоки Unicode с C ++ 0x или мне здесь чего-то не хватает?
В разделе [locale.codecvt] n2857 (последняя версия C + + 0x draft, что у меня под рукой) можно прочитать:
Специализация
codecvt
преобразует схемы кодирования UTF-16 и UTF-8, а также специализациюcodecvt
выполняет преобразование между схемами кодирования UTF-32 и UTF-8.codecvt
преобразует собственные наборы символов для узких и широких символов.В разделе [locale.stdcvt] мы находим:
Для аспекта
codecvt_utf8
: получим ли мы настоящие потоки Unicode с C ++ 0x или я что-то здесь упускаю?В разделе [locale.codecvt] n2857 (последний черновик C ++ 0x, который у меня есть) можно прочитать:
Специализация
codecvt
преобразует схемы кодирования UTF-16 в UTF-8, а специализацияcodecvt
преобразует между схемами кодирования UTF-32 и UTF-8.codecvt
преобразует собственные наборы символов для узких и широких символов.В разделе [locale.stdcvt] мы находим:
Для аспекта
codecvt_utf8
: получим ли мы настоящие потоки Unicode с C ++ 0x или я что-то здесь упускаю?В разделе [locale.codecvt] n2857 (последний черновик C ++ 0x, который у меня есть под рукой) можно прочитать:
Специализация
codecvt
преобразует схемы кодирования UTF-16 в UTF-8, а специализацияcodecvt
преобразует между схемами кодирования UTF-32 и UTF-8.codecvt
преобразует собственные наборы символов для узких и широких символов.В разделе [locale.stdcvt] мы находим:
Для аспекта
codecvt_utf8
: выполняет преобразование между схемами кодирования UTF-16 и UTF-8, а специализацияcodecvt
преобразует между схемами кодирования UTF-32 и UTF-8.codecvt
преобразует собственные наборы символов для узких и широких символов.В разделе [locale.stdcvt] мы находим:
Для аспекта
codecvt_utf8
: выполняет преобразование между схемами кодирования UTF-16 и UTF-8, а специализацияcodecvt
преобразует между схемами кодирования UTF-32 и UTF-8.codecvt
преобразует собственные наборы символов для узких и широких символов.В разделе [locale.stdcvt] мы находим:
Для аспекта
codecvt_utf8
: - Фасет должен преобразовывать многобайтовые последовательности UTF-8 в UCS2 или UCS4 (в зависимости от размера Elem) в программе. [...]Для фасета
codecvt_utf16
: - Фасет должен преобразовывать многобайтовые последовательности UTF-16 в UCS2 или UCS4 (в зависимости от размера Elem) в программе. [...]Для фасета
codecvt_utf8_utf16
: - Фасет должен преобразовывать многобайтовые последовательности UTF-8 в UTF-16 (один или два 16-битных кода) в программе.Так что, я думаю, это означает «да», но вам нужно быть более точным о том, что вы подразумеваете под "настоящими потоками Unicode", чтобы быть уверенным.
Я не знаю о wofstream. Но C ++ 0x будет включать новые типы символов distict (char16_t, char32_t) с гарантированной шириной и подписью (без знака), которые можно переносимо использовать для UTF-8, UTF-16 и UTF-32. Вдобавок появятся новые строковые литералы (u «Hello!» Для строкового литерала в кодировке UTF-16, например)
Ознакомьтесь с самым последним проектом C ++ 0x (N2960) .
Что касается вашего первого вопроса, то это мое предположение.
Библиотека IOStreams была построена в нескольких помещениях относительно кодирования. Например, для преобразования между Unicode и другими, не очень обычными кодировками предполагается, что.
Я считаю, что это причина существования двух шаблонных специализаций std :: codecvt. Один из них сопоставляется между типами char (возможно, вы просто работаете с ASCII), а другой - между wchar_t (внутренним для вашей программы) и char (внешними устройствами). Поэтому всякий раз, когда вам нужно выполнить преобразование в многобайтовую кодировку, вы должны делать это побайтово. Обратите внимание, что вы можете написать фасет, который обрабатывает состояние кодирования, когда вы читаете / записываете каждый байт из / в многобайтовую кодировку.
При таком подходе поведение стандарта C ++ становится понятным. В конце концов, вы используете строки в кодировке ASCII с широкими символами (при условии, что это значение по умолчанию на вашей платформе, и вы не переключили языковые стандарты). «Естественным» преобразованием будет преобразование каждого символа ASCII с расширенными символами в обычный (в данном случае один символ) символ ASCII. (Преобразование существует, и оно простое.)
Кстати, я не уверен, знаете ли вы, но вы можете избежать этого, создав фасет, который возвращает noconv для преобразований. Тогда у вас будет файл с расширенными символами.
При таком мышлении поведение стандарта C ++ понятно. В конце концов, вы используете строки в кодировке ASCII с широкими символами (при условии, что это значение по умолчанию на вашей платформе, и вы не переключили языковые стандарты). «Естественным» преобразованием было бы преобразование каждого символа ASCII с расширенными символами в обычный (в данном случае один символ) символ ASCII. (Преобразование существует, и оно простое.)
Кстати, я не уверен, знаете ли вы, но вы можете избежать этого, создав фасет, который возвращает noconv для преобразований. Тогда у вас будет файл с расширенными символами.
При таком мышлении поведение стандарта C ++ понятно. В конце концов, вы используете строки в кодировке ASCII с широкими символами (при условии, что это значение по умолчанию на вашей платформе, и вы не переключили языковые стандарты). «Естественным» преобразованием будет преобразование каждого символа ASCII с расширенными символами в обычный (в данном случае один символ) символ ASCII. (Преобразование существует, и оно простое.)
Кстати, я не уверен, знаете ли вы, но вы можете избежать этого, создав фасет, который возвращает noconv для преобразований. Тогда у вас будет файл с расширенными символами.
преобразование будет заключаться в преобразовании каждого символа ASCII расширенного символа в обычный (в данном случае один символ) символ ASCII. (Преобразование существует, и оно простое.)Кстати, я не уверен, знаете ли вы, но вы можете избежать этого, создав фасет, который возвращает noconv для преобразований. Тогда у вас будет файл с расширенными символами.
преобразование будет заключаться в преобразовании каждого символа ASCII расширенного символа в обычный (в данном случае один символ) символ ASCII. (Преобразование существует, и оно простое.)Кстати, я не уверен, знаете ли вы, но вы можете избежать этого, создав фасет, который возвращает noconv для преобразований. Тогда у вас будет файл с расширенными символами.
Проверьте это: Class basic_filebuf
Вы можете изменить поведение по умолчанию, установив широкий буфер char, используя pubsetbuf. Как только вы это сделаете, вывод будет wchar_t, а не char.
Другими словами, для вашего примера вы получите:
wofstream file(L"Test.txt", ios_base::binary); //binary is important to set!
wchar_t buffer[128];
file.rdbuf()->pubsetbuf(buffer, 128);
file.put(0xFEFF); //this is the BOM flag, UTF16 needs this, but mirosoft's UNICODE doesn't, so you can skip this line, if any.
file << someString; // the output file will consist of unicode characters! without the call to pubsetbuf, the out file will be ANSI (current regional settings)