Проблема такая: перебираю директории (пока) с помощью FindFirstFile/FindNextFile и сохраняю их в файле с помощью wofstream. Работаю с UNICODE. Вообщем некоректно записываются некоторые директории: напимер Räubern, вместо ä получается русский символ. В wostream писал и просто строку TCHAR и пробовал через basic_string<TCHAR>, не работает. Может кто сталкивался с таким? Использовать внешнюю библиотеку для работы с UNICODE-ом не хотелось бы, хотелось бы средствами C++. Еще интересно что, сохранил я строку Räubern в файл .txt (UNICODE). Теперь читаю это в basic_string<TCHAR> и вижу там такой вот буфер: 0xFFFE, 0x0052 (R), 0, 0x00e4 (ä), 0, 0x0075 (u), 0, ..... А в FileData.cFileName эта же строка выглядит так: 0x0052 (R), 0x00e4 (ä), 0x0075 (u) ...... То есть никаких 0xFFFE и нулевых слов между символами нет. Вообщем непонятно, зачем редактор пихает это 0xFFFE в файл, попытка записать эту константу в файл перед записью FileData.cFileName ни к чему хорошему не привели
Все что я написал внизу не совсем верно, и возможно я ошибаюсь но: Си и С++ не поддерживают unicode, они поддерживают широкие символы. Широкий символ - это тип который может вместить все символы текущей locale системы. Unicode есть UTF-32 BigEndian, UTF-32 LittleEndian, UTF-16 BE, UTF-16 LE, UTF-8 (и еще нескольколько). В Win32 под UNICODE и широкими символами понимается UTF-16 LE. Но все *W функции возвращают результат в Широких Символах. Поэто например в версии Windows для другой архитектуру UNICODE может быть уже UTF-16 BE или UTF-32 LE. 0xFFFE - это UNICODE BOM. т.е. ID кодировки в которой сохранен файл. Что теперь у тебя происходит с файлами. с помощью Find*FileW ты получаешь строку в Широких символах. С помощью wofstream ты сохраняешь в файл результат, но текст сохраняется в ansi кодировки текущей локали и поэтому несоответствие. (т.е. строка в UNICODE перекодируется в однобайтовую кодировку и уже сохраняется в файл) теперь при чтении из файла в широкую строку. Один байт преобразуется в широкий символ и получается. 52 в 0052, 00 в 0000, E4 в 00E4, 00 в 0000. т.е. все "широкие" функции в C/C++ читаю/записувают текстовой файл в ansi кодировки текущей локали. Но при чтении/записи происходит преобразования из 1-но байтового символа в 2-ух байтовый. Попробуй открывать файл не как текстовый, а как бинарный. и используй fwrite/stream->write для записи результата Find*FileW.
Неплохая заметка по теме (английский): http://blogs.msdn.com/oldnewthing/archive/2004/03/24/95235.aspx
Спасибо всем за полезную информацию. Вот что я выяснил. Похоже проблема в преобразовании типа из wchar_t в char при выводе в wstream. Поэтому приходися ручками выводить вторую половину слова. Думаю наверное можно даже будет пользоваться не wfstream, а просто fstream и самому написать операцию для вывода wchar_t. Write и ios_base::binary не помогают. Вот пример кода, который вроде работает. Единственная проблема это символ перевода строки '\n', который в файл пишется как 0x0D, 0x0A, а нам нужно 0x0D, 0x00, 0x0A, 0x00. При попытке же ручками записать 0x0D, 0x00, 0x0A, 0x00 получается 0x0D, 0x00, 0x0D, 0x0A, 0x00, т.е. 0x0A, автоматически превращается в 0x0D, 0x0A. Решение проблемы мне кажется в следущем: сначала формировать нужный буфер, потом парсить в нем 0x0D, 0x0A на 0x0D, 0x00, 0x0A, 0x00, а потом уже писать буфер в файл. Ну и конечно не забыть записать константу 0xFFFE в начало файла. Код (Text): wfstream dest; basic_string<TCHAR> str, str2; dest.open (_TEXT("b.txt")); if(!dest.is_open ()) abort (); str2 += 0x00FF; str2 += 0x00FE; dest << str2; if((hSearch = FindFirstFile (_TEXT ("*.*"), &FileData)) != INVALID_HANDLE_VALUE) { do { if(FileData. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { basic_string<TCHAR> str1; size_t j = _tcslen(FileData.cFileName); for(size_t i = 0; i < j; i++) { str1 += TCHAR(FileData.cFileName[i] & 0xFF); str1 += TCHAR(FileData.cFileName[i] >> 8); } dest << str1 << (TCHAR)0x000A; } } while(FindNextFile(hSearch, &FileData)); FindClose(hSearch); }
slayer Unicode -> filestream, вариант решения, ещё по теме. Странно, но получается что в текущем стандарте :-\
IceStudent Спасибо, то что нужно. А оказалось С++ действительно не поддерживает UNICODE, он ничего не знает об UNICODE. Он поддерживает расширенные символы, которые могут быть в кодировке UNICODE. p.s. Тему наверное можно закрывать