Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Использование Unicode в программе


Автор: Pilligrim 14.3.2007, 21:16
Решил перевести свою программу с ANSI на Unicode. Все хорошо, но вот какая проблемка: пишу в файл вот так:

Код

HANDLE file;
LPWSTR file_name;
LPWSTR string;
DWORD writebytes_len;
file = CreateFile(file_name,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
WriteFile(file,string,writebytes_len,&writebytes_len,NULL);
SetEndOfFile(file);
CloseHandle(file);


Все записывается без ошибок, но в файле явно символов больше, чем я записывал: 
во-первых, перед каждым символом есть какой-то еще один(причем один и тот же)
во-вторых, русские символы она записывает неправильно

Что делать?

Автор: ama_kid 14.3.2007, 21:37
А юникод продефайнен?

Автор: Pilligrim 14.3.2007, 21:40
Да:

Код

#define UNICODE
#define _UNICODE

Автор: dumb 15.3.2007, 04:41
Цитата(Pilligrim @  14.3.2007,  21:16 Найти цитируемый пост)
Что делать?

читать, что из себя представляет UNICODE. все вопросы сразу отпадут.

если кратко: записывается в файл у тебя именно "уникодная" строка - просто, судя по всему, ты не имеешь представления о том, как этот самый уникод выглядит... smile

Автор: Tectoder 15.3.2007, 13:02
Цитата(Pilligrim @  14.3.2007,  21:16 Найти цитируемый пост)
в файле явно символов больше, чем я записывал

Ага, в два раза. WriteFile записывает то что ей дают. Эта функция имеет одну реализацию, нет функций WriteFileA и WriteFileW
Если у тебя в программе юникод строки то они и записываются в файл.
Если тебе это не нравится нужно перед записью преобразовывать строки в анси. А после чтения преобразовывать обратно. Но тогда теряютяс плюсы юникода.
Как вариант - перед записью в файл перекодировать строку в кодировку UTF-8. Это "ужатый юникод", кодировка в которой число байт на символ зависит от самого символа. Если у тебя большинство символов английские это поможет сократить размер файла, но также это не лешает возможности писать в файл китайские, русские или ещекакиенибудьстранные символы.
Ну и конечно же надо понимать что такое юникод, прежде чем во всем этом разбираться. В этом может помочь одна из лучших вики-статей http://ru.wikipedia.org/wiki/юникод

Автор: Pilligrim 15.3.2007, 20:53
Цитата
Ага, в два раза. WriteFile записывает то что ей дают. Эта функция имеет одну реализацию, нет функций WriteFileA и WriteFileW
Если у тебя в программе юникод строки то они и записываются в файл.


Tectoder, оно конечно понятно, но все бы хорошо, если бы я, записывая строки юникод, мог бы потом и считать их. Но это не так... Например русские символы она записывает(а соответственно и считывает потом) не верно.

dumb, представление я имею, и то что символов больше я понимаю почему, но вот про русские символы я не понял до сих пор...

Читаю вот как:
Код

file = CreateFile(file_name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
ReadFile(file,&LPWSTR,readbytes_len,&readbytes_len,NULL);

Автор: Tectoder 15.3.2007, 21:24
Цитата(Pilligrim @  15.3.2007,  20:53 Найти цитируемый пост)
,&LPWSTR
 Все таки лучше писать полностью тот код, который вы используете, а не отредактированный фрагмент.

Автор: Pilligrim 16.3.2007, 21:14
Привожу код:
Код


HWND hwndLB;//ListBox

enum CACHE_TYPE
    {BASE_END,//Reserved: обозначает конец базы файлов
     BASE_BEGIN,//Reserved
     FILE_LINK,
     TEXT_FRAG
    };

struct CACHE
    {CACHE_TYPE type;
     wchar_t* string;
    };
//Save_DATA сохраняет базу данных
void wSave_DATA(LPWSTR file_name)
        {HANDLE file;
     DWORD writebytes_len;
          bool writeresult;
     DWORD str_len;
     int item_data;
     CACHE* lpcache;
     UINT item_num;
     int base_end;
            
     if(file_name==NULL) return;

     file = CreateFile(file_name,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_         ATTRIBUTE_NORMAL,NULL);
     if(file==INVALID_HANDLE_VALUE) return;

     for(item_num=0;;item_num++)
             {item_data=SendMessageW(hwndLB,LB_GETITEMDATA,item_num,item_num); 
               
             if(item_data == LB_ERR) break;

             lpcache = (CACHE*)item_data;
               
             writebytes_len = sizeof(lpcache->type);
             writeresult = WriteFile(file,&lpcache->type,writebytes_len,&writebytes_len,NULL);
             if(writeresult && writebytes_len==0)
                      break;

             str_len = lstrlenW(lpcache->string);
             str_len = str_len*sizeof(TCHAR);
             writebytes_len = sizeof(str_len);
             writeresult = WriteFile(file,&str_len,writebytes_len,&writebytes_len,NULL);
             if(writeresult && writebytes_len==0)
                 break;

                  writebytes_len = str_len;
             writeresult = WriteFile(file,lpcache->string,writebytes_len,&writebytes_len,NULL);
             if(writeresult && writebytes_len==0)
            break;
             lpcache = NULL;
             }
     base_end = BASE_END;
     writebytes_len = sizeof(base_end);
     writeresult = WriteFile(file,&base_end,writebytes_len,&writebytes_len,NULL);
     SetEndOfFile(file);
     CloseHandle(file);
    }

//Load_DATA загружает базу данных     
bool wLoad_DATA(LPWSTR file_name)
       {HANDLE file;
         wchar_t data[MAX_PATH];
         CACHE_TYPE type;
         DWORD readbytes_len;
         bool readresult;
         DWORD str_len;

         if(file_name==NULL) return false;
         if(!wCheckFileType((LPWSTR)file_name,L"fls") && !wCheckFileType((LPWSTR)file_name,L"bfr")) 
             return false;          
         file = CreateFile(file_name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_                ATTRIBUTE_NORMAL,NULL);
         if(file==INVALID_HANDLE_VALUE) return false;
         SendMessageW(hwndLB,LB_RESETCONTENT,0,0);

         readbytes_len = 4;               
         readresult = ReadFile(file,&type,readbytes_len,&readbytes_len,NULL);          
         while(1)
                 {readbytes_len = sizeof(type);               
                 readresult = ReadFile(file,&type,readbytes_len,&readbytes_len,NULL);
                 if(readresult && readbytes_len==0) 
              {CloseHandle(file);
                return true;}

                 if(type==BASE_END) 
                       {CloseHandle(file);
                         return true;}

                 readbytes_len = sizeof(str_len);               
                 readresult = ReadFile(file,&str_len,readbytes_len,&readbytes_len,NULL);
                 if(readresult && readbytes_len==0) 
                       {CloseHandle(file);
                         return true;}
               
                 str_len = str_len*sizeof(TCHAR);
                 readbytes_len = str_len;
                 readresult = ReadFile(file,data,readbytes_len,&readbytes_len,NULL);
                 if(readresult && readbytes_len==0) 
                         {CloseHandle(file);
                           return true;}
                 data[readbytes_len] = 0x0000;
                 wAdd_DATA(type,data);
                 }
    CloseHandle(file);
    return true;
}



Код прямо из проги вырвал. Если какие-нить переменные не объявлены - спрашивайте.

Автор: Pilligrim 18.3.2007, 19:50
Всем спасибо! 

Проблемы оказывается и не было, это все Блокнот виндовский. Он виноват!!! Он юникод каряво понимает как-то... 

Все ОК)))

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)