问题
I have a slight problem reading data from file. I want to be able to read wstring's, aswell as a chunk of raw data of arbitrary size (size is in bytes).
std::wfstream stream(file.c_str());
std::wstring comType;
stream >> comType;
int comSize;
stream >> comSize;
char *comData = new char[comSize];
memset(comData, 0, comSize);
stream.read(comData, comSize);
//error C2664 : 'std::basic_istream<_Elem,_Traits>::read'
// : cannot convert parameter 1 from 'char *' to 'wchar_t *'
Perhaps I am using wrong streams, or something along those lines. Basically, I want to read a wstring, size of the data followed (which could be any number of bytes), followed by that many bytes of component data. Obviously, I can't read char's because the template assumes wchar_t's.
I can read wchar_t's but then I have to make sure the data is stored as aligned by sizeof(wchar_t). Otherwise, I could end up corrupting the stream. A scenario would be when the data is 15 bytes. I would have to read 16 bytes, then mask the unwanted byte, seek the stream to 15 bytes offset (if possible with wchar_t templated?) to be able to read the next data chunk.
Clearly, there should be a nicer way of achieving what I am trying to do.
回答1:
the problem with the stream.read is that it uses wchar_t as "character unit" with wfstream. If you use fstream it uses char as "character unit".
This would work if you want to read wide characters:
wchar_t *comData = new wchar_t[comSize];
stream.read(comData, comSize);
Also 15 bytes of data can't be read with a wide stream, because the smallest unit is at least 2bytes (see below), so you can only read chunks of sizwof(wchar_t) * n.
But if you are concerned about portability of the application wfstream/wchar_t is maybe not the best solution because there is no standard how wide wchar_t is (e.g. on windows wchar_t is 16bit on many unix/linux systems it is 32bit).
The second problem with storing text as wide characters is endianess, i would suggest to use UTF-8 for text storage.
回答2:
Considering your requirements I do not think wfstream is the way to go. Considerer using something like the following code snippet.
#include "stdafx.h"
#include <fstream>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
std::wstring str(L"hello");
size_t size1 = str.length();
char data[] = { 0x10, 0x20, 0x30 };
size_t size2 = 3;
FILE* output = NULL;
if (_wfopen_s(&output, L"c:\\test.bin", L"wb") == 0) {
fwrite(&size1, sizeof(size_t), 1, output);
fwrite(str.c_str(), size1 * sizeof(wchar_t), 1, output);
fwrite(&size2, sizeof(size_t), 1, output);
fwrite(data, size2, 1, output);
fclose(output);
}
FILE* input = NULL;
if (_wfopen_s(&input, L"c:\\test.bin", L"rb") == 0) {
fread(&size1, sizeof(size_t), 1, input);
wchar_t* wstr = new wchar_t[size1 + 1];
fread(wstr, size1 * sizeof(wchar_t), 1, input);
std::wstring str(wstr, size1);
delete[] wstr;
fread(&size2, sizeof(size_t), 1, input);
char* data1 = new char[size2];
fread(data1, size2, 1, input);
std::wcout << str.c_str() << std::endl;
for (size_t i = 0; i < size2; ++i) {
std::wcout << std::hex << "0x" << int(data1[i]) << std::endl;
}
delete[] data1;
fclose(input);
}
return 0;
}
This outputs:
hello
0x10
0x20
0x30
回答3:
# ifdef UNICODE
# define tfstream wfstream
# else
# define tfstream fstream
# endif
tfstream fs( _T("filename.bin"), tfstream::binary );
byte buffer[1023];
fs.read( buffer, sizeof(buffer) )
I think, the _T("filename.bin") and tfstream are the UI expression; the buffer and the read() is DATA LOGIC expression. wfstream must NOT restrict the buffer to the type wchar_t. The UI must NOT mix with DATA LOGIC ! wfstream do the wrong thing here
来源:https://stackoverflow.com/questions/161852/how-can-i-read-binary-data-from-wfstream