Внезапно: ассемблерная команда xlat Либо кургузый паровоз из MultiByteToWideChar и WideCharToMultiByte.
Я так понимаю юникод нельзя на ХР сп3 перевести в UTF8 через WideCharToMultiByte ? Вот код программы, он отлично переводить DOS -> CP_1251, CP_1251 -> DOS, UTF8 -> CP_1251/DOS, а вот так чтоб на выходе был UTF8, никак... GetLastError() возвращает 1004(что значит неверный флаг). Думал поставить WC_ERR_INVALID_CHARS как флаг, но он для висты и више (. Есть ли какой то способ на WINAPI сделать чтоб и UTF8 работал ? Код (Text): #include "stdafx.h" #include "windows.h" #define F1 0 #define F2 1 #define C1 2 #define C2 3 #define C3 3 UINT GetCharSet(char *name) { if (_stricmp(name,"DOS") == 0) return CP_OEMCP; if (_stricmp(name,"KOI8") == 0) return CP_UTF8; if (_stricmp(name,"CP_1251") == 0) return CP_ACP; return -1; }; int main(int argc, char* argv[]) { DWORD s,s1; char * buf; HANDLE h; UINT CodePage1 = GetCharSet(argv[1]),CodePage2=GetCharSet(argv[2]); WCHAR * wbuf = 0; if ((CodePage1 == -1) | (CodePage2 == -1)) { MessageBox(0,"unknow char set\n","ERROR",MB_ICONERROR); return -1; }; h = CreateFile(argv[3],GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if (h == INVALID_HANDLE_VALUE) { MessageBox(0,"can'nt open file\n","ERROR",MB_ICONERROR); return -1; }; s = GetFileSize(h,0); buf = new char [s+1]; buf[s] = 0; ReadFile(h,&buf[0],s,&s,0); CloseHandle(h); // переобразование текста в юникод s1=MultiByteToWideChar(CodePage1,MB_ERR_INVALID_CHARS,buf,-1,0,0); if (s1 == 0) { MessageBox(0,"Convert Error","ERROR",MB_ICONERROR); return -1; }; wbuf = new WORD[s1+1]; wbuf[s1] = 0; s1=MultiByteToWideChar(CodePage1,MB_ERR_INVALID_CHARS,buf,-1,wbuf,s1); //переобразование из юникода в заданую кодировку s1 = WideCharToMultiByte(CodePage2,WC_COMPOSITECHECK,wbuf,-1,buf,0,(const char*)0,false); GetLastError(); if (s1 == 0) { MessageBox(0,"Convert Error","ERROR",MB_ICONERROR); return -1; }; delete[] buf; buf = new char [s1 + 1]; buf[s1] = 0; s1 = WideCharToMultiByte(CodePage2,WC_COMPOSITECHECK,wbuf,-1,buf,s1,(const char*)0,false); //запись результата в файл h = CreateFile(argv[4],GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); if (h == INVALID_HANDLE_VALUE) { MessageBox(0,"Can'nt create file","ERROR",MB_ICONERROR); return -1; }; WriteFile(h,(void*)buf,s1,&s1,0); CloseHandle(h); MessageBoxW(0,wbuf,(WORD*)"",0); MessageBox(0,"All compleat","GOOD",MB_OK | MB_SYSTEMMODAL); delete [] wbuf; delete [] buf; return 0; }
Вроде ж в MSDN чётко сказано: для UTF-8 dwFlags или 0 или WC_ERR_INVALID_CHARS. Раз не Vista, значит должен быть 0. Я попробовал, по крайней мере русские буквы берёт на "ура". lpUsedDefaultChar, кстати, не BOOL а указатель на него.
XshStasX Код (Text): char *to_utf8(const char *ascii) { char *utf8 = NULL; WCHAR *wide = NULL; int len; if (0 == IsBadStringPtr(ascii, (UINT_PTR ) -1)) { len = MultiByteToWideChar(CP_ACP, 0, ascii, -1, NULL, 0); if (0 != len) { wide = (WCHAR *) GlobalAlloc(GPTR, sizeof(WCHAR) * len); if (NULL != wide) { if (0 != MultiByteToWideChar(0, 0, ascii, -1, wide, len)) { len = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, 0, 0); if (0 != len) { utf8 = (char *) GlobalAlloc(GPTR, sizeof(char) * len); if (NULL != utf8) { if (0 == WideCharToMultiByte(CP_UTF8, 0, wide, -1, utf8, len, 0, 0)) { GlobalFree((HGLOBAL) utf8); utf8 = NULL; } } } } GlobalFree((HGLOBAL) wide); wide = NULL; } } } return utf8; }
q_q спасибо ) В чем преимущество брать память из кучи а не к примеру через VirtualAlloc ? А насколько быстрей GlobalAlloc от VirtualAlloc ? Или разница только в том что VirtualAlloc выделяет по 64кб ?
А как быть с KOI8 ее тоже нужно перевести в Unicode и обратно ? WideCharToMultiByte/MultiByteToWideChar я так понимаю они не катят (... Желательно без сторонних библиотек, но если никак то можно и их.
http://www.wasm.ru/forum/viewtopic.php?id=27860 http://www.wasm.ru/forum/viewtopic.php?pid=313226#p313226