Написал приложение на Visual C++ 2010 express. Выяснилось что в выходной файл также должны писаться и кирилица. Файл должен быть в кодировки utf-8. Заменил
ofstream на owstream. И если раньше просто выходила неверная кодировка, то теперь при попытки записать строку содержащую кирилицу. Поток обрывается на начале кирилице. (Файл XML) Посоветуйте как правильно работать с кирилицей.
Вот куски кода.
...
wofstream xml;
...
xml.open("output.xml");
...
xml << "path=\""<< fname <<"\" "; // < тут происходит обрыв потока... например строку вида "D:\backup\section один" пишет в файл как D:\backup\section и все дальше в файл ничего не попадает.
...
Попробовал следующий упрощенный вариант... результат тот же, пишет только латиницу.
#include "stdafx.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
wofstream xml;
wstring s0 = L"example cyrilic and latin text Кириллица и латинский текст";
xml.open("output.txt");
xml << L"example cyrilic and latin text Кириллица и латинский текст" << endl;
//xml << s0 << endl; <-тут такой же результат как и выше... записывается только латиница.
return 0;
}
Попробовал добавить setlocale(LC_ALL, "ru_RU.UTF-8");... результат прежний.
Да в тестовом упрощенном видно... в полной версии.. (листинг большой и разбит на несколько файлов) проблема осталась...
Вышел из положения вернувшись обратно к ofstream. И пишу строки использую cp2utf....
void cp2utf( char* str, char* res ) {
static const long utf[ 256 ] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,
59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,
87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,
111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,1026,1027,8218,
1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,
8220,8221,8226,8211,8212,8250,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,
164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,
183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,
1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,
1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,
1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,
1096,1097,1098,1099,1100,1101,1102,1103
};
int cnt = strlen( str ),
i = 0, j = 0;
for(; i < cnt; ++i ) {
long c = utf[ (unsigned char) str[ i ] ];
if( c < 0x80 ) {
res[ j++ ] = c;
}
else if( c < 0x800 ) {
res[ j++ ] = c >> 6 | 0xc0;
res[ j++ ] = c & 0x3f | 0x80;
}
else if( c < 0x10000 ) {
res[ j++ ] = c >> 12 | 0xe0;
res[ j++ ] = c >> 6 & 0x3f | 0x80;
res[ j++ ] = c & 0x3f | 0x80;
}
}
res[ j ] = '\0';
}
Всем спасибо за помощь. К сожалению проблему с wofstream не решил. Необходимого функционала добился способом описанным выше.
Ответ
@Сфинкс, комментарии кончились, поэтому в ответе.
Вы несомненно поступили правильно. На практике я бы сделал так же (только на чистом Си, но дело не в этом.)
Просто странно, что с С++ не получилось. Конечно, у меня пример из линукса (пришлось доставить ru_RU.cp1251 локаль), по умолчанию у меня en_US.UTF-8. Но в принципе, в винде д.б. utf локаль, например та же "en_US.utf-8",
так что пример может пригодиться.
#include
#include
#include
using namespace std;
int main (int ac, char *av[])
{
cout << "Hi
";
wofstream os;
os.open("test.ws");
os.imbue(locale(av[1] && *av[1] == 'c' ? "ru_RU.cp1251" : "en_US.utf-8"));
os << "1 aa xaxa xoxo wofstream
" << L"zz рус бук
";
os.close();
cout << "End
";
return 0;
}
А вот результат
avp@avp-xub11:~/hashcode$ g++ wofstream.cpp
avp@avp-xub11:~/hashcode$ ./a.out
Hi
End
avp@avp-xub11:~/hashcode$ cat test.ws
1 aa xaxa xoxo wofstream
zz рус бук
avp@avp-xub11:~/hashcode$ ./a.out cp1251
Hi
End
avp@avp-xub11:~/hashcode$ cat test.ws
1 aa xaxa xoxo wofstream
zz ��� ��
avp@avp-xub11:~/hashcode$ iconv -f cp1251 -t utf-8 test.ws
1 aa xaxa xoxo wofstream
zz рус бук
avp@avp-xub11:~/hashcode$
Хочу отметить, что в тексте программы русские буквы набиты в utf-8. Если убрать L перед константой, то перекодировки (если ее задавать) не будет.
Также никакой перекодировки нет, если заменить wofstream на ofstream (естественно модификатор L для ofstream надо убрать).