2
std::wifstream theFileHandle;
std::wstring theData;
theFileHandle.open( theFile.Name() );
theFileHandle >> theData;
theFileHandle.close();

Could anyone tell me why my string (theData) is only getting the first word from the file (theFile) ??? I would like the string to contain all of the text from the file including white spaces and new lines, does anyone have a suggestion for this? Thank you.

PS. I need the data to be preserved perfectly. Thanks.

Christopher Peterson
  • 973
  • 6
  • 20
  • 32
  • 4
    I can guarantee that the `>>` operator is in fact working correctly. – Ed S. Feb 10 '11 at 01:00
  • possible duplicate of [Read whole ASCII file into C++ std::string](http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring) – Ben Voigt Feb 10 '11 at 01:10
  • Re your PS "need the data to be preserved perfectly", a C++ wide stream **may not do what you think it does**. It interprets the file as narrow characters (e.g. in Windows, as ANSI) and serves you corresponding wide characters (e.g., Unicode). It may work in *nix with UTF-8 encoded file, I don' know, but in Windows, if the file is Unicode you'll get garbage. Yes, it's daft. Yes, it's nearly impossible to think of any reasonable rationale for that design. And no, it's not Microsoft's fault, it's the C++ iostreams design. One fix is to read as binary data, and translate yourself. Cheers, – Cheers and hth. - Alf Feb 10 '11 at 01:48
  • @Alf P. Steinbach: Just supply a codecvt facet that does the conversion you want and the iostreams design is just fine. MSVC comes with one for UTF-16LE iirc. – Billy ONeal Feb 10 '11 at 02:19

4 Answers4

4

The reason you're only getting the first word is that this is precisely how the >> operator works when applied to strings - it just gets the first whitespace-delimited token from whatever stream you're reading from, after skipping any leading whitespace.

If you want to read the entire contents of the file, you can use the getline function like this:

std::wifstream theFileHandle;
theFileHandle.open( theFile.Name() );

std::wstringstream data;
for (std::wstring line; getline(theFileHandle, line); )
    data << line << L"\n";

std::wstring theData = data.str();

This loops while more data can be read via getline and thus pulls all the data from the file. Since getline skips over newlines, this approach also adds the newlines back in.

EDIT: As pointed out by @PigBen, there is a much cleaner way to do this using rdbuf():

std::wifstream theFileHandle;
theFileHandle.open( theFile.Name() );

std::wstringstream data;
data << theFileHandle.rdbuf();

std::wstring theData = data.str();

This uses the fact that the stream insertion operator is overloaded to take in a stream buffer. The behavior in this case is to read the entire contents of the stream buffer until all of the data has been exhausted, which is exactly the behavior you want.

templatetypedef
  • 328,018
  • 92
  • 813
  • 992
3

operator>> for a string is defined to work pretty much the same as the %s conversion for scanf, which only reads until it encounters white space.

There are a number of ways of reading an entire file into a string. The simplest is probably:

std::wstringstream buffer;
buffer << theFileHandle.rdbuf();
theData = buffer.str();

If you're dealing with a big file, there's at least one way that's clearly faster. See Test Four in an answer I posted previously (but that code is Martin York's, not mine).

Community
  • 1
  • 1
Jerry Coffin
  • 437,173
  • 71
  • 570
  • 1,035
1

That's how >> is supposed to work. It extracts formatted data from the input stream. You want .read() which extracts unformatted data.

see more here: http://www.cplusplus.com/reference/iostream/istream/read/

e.g.:

std::wifstream theFileHandle;
wchar_t theData[SOME_LARGE_VALUE];
theFileHandle.open( theFile.Name() );
theFileHandle.read(theData, sizeof(theData));
theFileHandle.close();
Tim
  • 8,474
  • 3
  • 37
  • 54
1

See excellent previous answer for a concise way of reading in the whole file, and doing it efficiently.

Community
  • 1
  • 1
Keith
  • 6,536
  • 16
  • 22