tags:

views:

77

answers:

2

Say I want to read the contents of a file using basic_filebuf. I have a type called boost::uintmax_t which has a size of 8 bytes. I am trying to write the following:

typedef basic_filebuf<uintmax_t> file;
typedef istreambuf_iterator<uintmax_t> ifile;

file f;
vector<uintmax_t> data, buf(2);

f.open("test.txt", std::ios::in | std::ios::binary);
f.pubsetbuf(&buf[0], 1024);

ifile start(&f), end;
while(start != end)
{
    data.push_back(*start);
    start++;
}

The problem is that some of the bytes get read, others don't. For example, lets say there are 9 bytes in the file numbered 1-9:

|1|2|3|4|5|6|7|8|9|

When I run the above code, only one element is pushed back into data, which contains 4 bytes only from the original data in f:

[0|0|0|0|4|3|2|1] --> only element in [data]

What am I doing wrong? This is my first time to use basic_filebuf directly, though I know how to use filebuf.

A: 

Objects of type basic_filebuf are created with an internal buffer of type char * regardless of the char_type specified by the type parameter Elem. This means that a Unicode string (containing wchar_t characters) will be converted to an ANSI string (containing char characters) before it is written to the internal buffer. To store Unicode strings in the buffer, create a new buffer of type wchar_t and set it using the basic_streambuf::pubsetbuf() method.

from http://msdn.microsoft.com/en-us/library/tzf8k3z8%28VS.80%29.aspx

wrang-wrang
Thanks. Even if I use pubsetbuf() the value of (*start) is only correct for 4 bytes only, the other for bytes are zeros. :)
AraK
+4  A: 

A basic_filebuf deals with an "internal" char type and an "external" one. The "external" one is the contents of the file, and is always bytes. The "internal" one is the template parameter, and is the one used in its interface with the program. To convert between the two, basic_filebuf uses the codecvt facet of its locale.

So if you want it to write directly the bytes you give it, you have two options:

  • use a "degenerate" codecvt that only casts between the "internal" and "external" encodings instead of trying to perform a conversion.
  • use a basic_filebuf, make sure to use the "classic" locale, and do the cast to char yourself
Éric Malenfant