typedef struct {
char c[20];
int i;
} header;
void foo(std::string s) {
std::ifstream ifs(s.c_str(), std::ios_base::binary | std::ios_base::in);
if (ifs) {
std::filebuf* pbuf = ifs.rdbuf();
pbuf->pubseekpos(std::ios_base::beg);
// ... ?
}
}
I'm trying to read a file in binary mode the C++ way, I can't identify the right method to call for reading the bits from the file, there is a read
for ifstream
but if I'm supposed to use that method, what is the point of filebuf
?
To simplify things I have a struct
that represents the order, the size and the fields of the header and I hope that there will be a method that would just keep and instance of this struct and write the bits in right fields just like fread
from C.
Someone can clarify the point of filebuf
and what method should I use when reading a file through an unformatted stream of data ?
Just use basic_istream<>::read()
to read raw, unformatted byte data:
void foo(std::string s) {
std::ifstream ifs(s.c_str(), std::ios_base::binary | std::ios_base::in);
if (ifs) {
char buffer[20];
if (!ifs.read(buffer, 20)) {
// Handle error
}
}
}
First, the real point of filebuf
is that it derives from
streambuf
, and that an istream
whose streambuf is a filebuf
will behave largely like an ifstream
. This is important; the
>>
operator aren't virtual, and since many of them aren't
members, they cannot be virtual. All input must pass through
the istream
, not the ifstream
that's derived from it. More
generally, the ifstream
can be thought of as just
a convenience class; it's constructor provides the istream
base class with a filebuf
, its destructor destructs the
filebuf
, and it provides access to the functionality of
filebuf
which isn't present in the base streambuf
.
That doesn't mean that you cannot use the streambuf
directly,
you can, and there are cases where it is appropriate. But if
you do, you have to take care of the error handling. When you
call istream::read
asking for a certain number of bytes, and
those bytes aren't there, istream::read
will note the end of
file, set the necessary error bits, and provide the count of
what was actually read through istream::gcount
. If you're
reading byte by byte, and don't know how many bytes there might
be, then all of that may not mean much (but you'll probably want
to set eofbit
if you see EOF). If you're trying to read
a specific number of bytes (say a four byte integer), then
istream:read
will set the appropriate error bits if you cannot
read four bytes, so you can easily test for the error.
EDIT
One additional comment: you should probably put the reading of
the file in a separate process, which takes an std::istream&
.
You really don't want the reading code to know that it is
dealing with an ifstream
, rather than some other sort of
stream. (Also: there's no need to seek if you've just opened
the file.)
there is a
read
forifstream
Yes, and that's what you use to read unformatted data from the stream; hence the name.
if I'm supposed to use that method, what is the point of
filebuf
?
It's used by the stream to handle low-level file access and buffering. You can access it if you need to mess around with those details, but usually there's no need to. You certainly wouldn't mess around with it if you just want to read from the stream.
what is the point of filebuf ?
None, here.
I can't see why you're using it.
Until you do more complex operations, filebuf
is an implementation detail†.
† (Sort of.)
来源:https://stackoverflow.com/questions/21049909/read-equivalent-for-filebuf