I'm trying to develop a small Windows application to improve my C++ skill outside MFC framework and to help my studies about foreign languages.
I would like to make a small, personal and easy-to-port_and_use dictionary and, while I have no problems in developing the GUI, I'm having real pain in saving and restoring data.
My idea is to write down a binary files structured as follow:
int (representing the number of words)
int (representing the string length + \0)
sequence of characters zero-terminated.
Now, I'm learning russian and my primary language is italian, so I can't use plain old std::string to write down words, moreover, thank you Microsoft, I'm using VS2010 with all the goods and bads that come with it. I'm showing you my routines to write down int and wstring://Writing int
void CDizionario::ScriviInt( int nInt, wofstream& file ) const
{
file.write( reinterpret_cast < const wchar_t * > ( &nInt ), sizeof( nInt ) );
file.flush();
}
// Writing string
void CDizionario::ScriviWString( int nLStringa, const wstring* pStrStringa, wofstream& file ) const
{
wchar_t cTerminatore;
string strStringa;
file.write( pStrStringa->c_str(), nLStringa );
file.flush();
cTerminatore = L'\0';
file.write( &cTerminatore, sizeof( wchar_t ) );
file.flush();
}
// Reading int
void CDizionario::LeggiInt( int *pInt, wifstream& file )
{
file.read( reinterpret_cast < wchar_t * >( pInt ), sizeof( int ) );
}
// Reading wstring
void CDizionario::LeggiWString( int nLStringa, wstring& strStringa, wifstream& file )
{
wchar_t *pBuf;
streamsize byteDaLeggere;
byteDaLeggere = nLStringa;
pBuf = new wchar_t[(unsigned int)( byteDaLeggere * sizeof( wchar_t ) )];
file.read( pBuf, byteDaLeggere * sizeof( wchar_t ) );
strStringa.append( pBuf );
delete [] pBuf;
}
// Constructor
CDizionario::CDizionario( void )
{
m_pLoc = new locale( locale::classic(), new codecvt_utf8_utf16 );
}
// Somewhere in my code before calling LeggiInt/ScriviInt/LeggiWString/ScriviWString:
// ...
file.imbue( *m_pLoc );
Well, my first test has been: ciao - привет, result:
01 00 ee bc 90 22 05 00 ee bc 90 22 63 69 61 6f
00 ec b3 8c 07 00 ee bc 90 22 d0 bf d1 80 d0 b8
d0 b2 d0 b5 d1 82 00 ec b3 8c
Numbers are read correctly, the problem comes when I write down strings: I'd expect that ciao (63 69 61 6f 00 ec b3 8c) was written in 10 bytes (wchar_t size) and not in 5, as happens for russian translation ( d0 bf d1 80 d0 b8 d0 b2 d0 b5 d1 82 00 ec b3 8c).Obviously I'm missing something, but I can't figure what it is. Can you guys help me out? Also, if you know a better approach to solve the problem, I'm open minded.
EDIT: SOLUTION
Following the first of the two method presented by @JamesKanze, I've decided to sacrify some portability and let the system do my homework:
void CDizionario::LeggiInt( int *pInt, ifstream& file )
{
file.read( reinterpret_cast( pInt ), sizeof( int ) );
}
void CDizionario::LeggiWString( int nLStringa, wstring& strStringa, ifstream& file ) { char *pBuf; streamsize byteDaLeggere; wstring_convert> converter; byteDaLeggere = nLStringa; pBuf = new char[byteDaLeggere]; file.read( pBuf, byteDaLeggere ); strStringa = converter.from_bytes( pBuf ); delete [] pBuf; }
void CDizionario::ScriviInt( int nInt, ofstream& file ) const { file.write( reinterpret_cast( &nInt ), sizeof( nInt ) ); file.flush(); } void CDizionario::ScriviWString( const wstring* pStrStringa, ofstream& file ) const { char cTerminatore; string strStringa; wstring_convert> converter; strStringa = converter.to_bytes( pStrStringa->c_str() ); ScriviInt( strStringa.length() + 1, file ); file.write( strStringa.c_str(), strStringa.length() ); file.flush(); cTerminatore = '\0'; file.write( &cTerminatore, sizeof( char ) ); file.flush(); }