Господа, помогите, я столкнулся с проблемой.
Надо в файл скинуть бинарные данные.
Имя файла в широких символах.
#include <fstream>
#include <tchar.h>
...
std::wfstream wfile(_T("мой файл"), std::ios_base::out | std::ios_base::binary);
if(wfile.is_open())
{
std::string strEng = "bingo";
wfile.write(reinterpret_cast<const wchar_t*>(strEng.c_str()), strEng.length());
wfile.flush();
}
wfile.close();
Естественно, ничего и не записывает из-за неправильного приведения типов.
Размер нужно указывать, как количество двухбайтных символов wchar_t, а надо
записать допустим 5 байт (строка char символов).
Что делать? (желательно, без локалей)
Здравствуйте, pick_catcher, Вы писали:
_>Господа, помогите, я столкнулся с проблемой.
_>Надо в файл скинуть бинарные данные.
_>Имя файла в широких символах.
_>#include <fstream>
_>#include <tchar.h>
_>...
_>std::wfstream wfile(_T("мой файл"), std::ios_base::out | std::ios_base::binary);
_>if(wfile.is_open())
_>{
_> std::string strEng = "bingo";
_> wfile.write(reinterpret_cast<const wchar_t*>(strEng.c_str()), strEng.length());
_> wfile.flush();
_>}
_>wfile.close();
_>Естественно, ничего и не записывает из-за неправильного приведения типов.
_>Размер нужно указывать, как количество двухбайтных символов wchar_t, а надо
_>записать допустим 5 байт (строка char символов).
_>Что делать? (желательно, без локалей)
Если для Visual Studio, то там есть перегрузка конструктора fstream для широких символов
std::fstream file( L"мой файл", std::ios_base::out | std::ios_base::binary );
if( file )
{
std::string str = "bingo";
file.write( str.c_str(), str.length() );
file.flush();
}
Поясню суть проблемы еще раз.
Если в конструкторе использовать широкие символы (имя файла — что очень хочеться), то записывать в файл тоже
придется широкие символы, то есть 3 байта записать не удасться, можно либо 2 либо 4 !!! (добавлять байт к буферу, до четного размера считаю извращением).
Если использовать, как обычно ANSI символы, то возникают проблемы с именем файла — нужно грамотно использовать локализацию,
чего я не умею (видел примеры с претензиями на кроссплатформенность — так там полсотни строк нечитаемого кода).
Вот и не знаю, что делать, похоже придется извращаться...
Здравствуйте, pick_catcher, Вы писали:
_>Поясню суть проблемы еще раз.
_>Если в конструкторе использовать широкие символы (имя файла — что очень хочеться), то записывать в файл тоже
Это если использовать wfstream, а не fstream. Иногда встречается перегрузка для fstream, которая принимает имя в виде wchar_t.
_>придется широкие символы, то есть 3 байта записать не удасться, можно либо 2 либо 4 !!! (добавлять байт к буферу, до четного размера считаю извращением).
_>Если использовать, как обычно ANSI символы, то возникают проблемы с именем файла — нужно грамотно использовать локализацию,
_>чего я не умею (видел примеры с претензиями на кроссплатформенность — так там полсотни строк нечитаемого кода).
_>Вот и не знаю, что делать, похоже придется извращаться...
Можно придумать такие извращения.
Использовать boost (да святится имя Его):
#include <boost/filesystem/fstream.hpp>
namespace fs = boost::filesystem;
fs::fstream file( L"мой файл.txt", std::ios_base::out | std::ios_base::binary );
if( file.is_open() )
{
std::string str = "bingo";
file.write( str.c_str(), (std::streamsize) str.length() );
file.flush();
}
Либо проимитировать его действия:
std::wstring name = L"мой файл";
// создаём файл
{
HANDLE handle = CreateFileW( name.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
CloseHandle( handle );
}
// Получаем короткую форму (8.3) имени
std::wstring short_form;
for( DWORD size = (DWORD) name.size() + 1; ; )
{
boost::scoped_array< wchar_t > buffer( new wchar_t[ size ] );
DWORD len = ::GetShortPathNameW( name.c_str(), buffer.get(), size );
if( len == 0 )
{
// шота не то
return -1;
}
if( len <= size )
{
short_form.assign( buffer.get(), len );
break;
}
size = len + 1;
}
// Сужаем
std::string narrow;
{
int size = ::WideCharToMultiByte( CP_ACP, 0,
short_form.c_str(), (int) short_form.size(), 0, 0, 0, 0 );
boost::scoped_array< char > buffer( new char[ size ] );
::WideCharToMultiByte( CP_ACP, 0,
short_form.c_str(), (int) short_form.size(),
buffer.get(), size, 0, 0 );
narrow.assign( buffer.get(), size );
}
// Открываем файл
std::fstream file( narrow.c_str(), std::ios_base::out | std::ios_base::binary );
if( file.is_open() )
{
std::string str = "bingo";
file.write( str.c_str(), (std::streamsize) str.length() );
file.flush();
}
Таким способом действует boost.filesystem.
Не знал, что в boost'е есть аналог fstream'а.
СПАСИБО!!!