Smash
Smash

Reputation: 3802

C++ Read/Write to textfile issue

I need to write numbers and text in a text file, for an unknown reason, the writing works, the reading does not, the problem is reading the text as in the following example:

fstream ff,ff2;
int a,b;
ff.open("simtestagain.txt",ios::out);
CString mycstring = _T("Name with spaces");
char mycharbuffer[255];         //destination buffer
size_t convertedChars = 0;      //number of characters converted
wcstombs_s( &convertedChars, mycharbuffer, mycstring.GetLength()+1,mycstring.GetBuffer(), _TRUNCATE);
ff << 1 << endl;
ff << mycharbuffer << endl; 
ff << 2 << endl;

ff.close();

ff2.open("simtestagain.txt",ios::in);

ff2 >> a;
ff2.getline(mycharbuffer,255);
mycstring = mycharbuffer;
ff2 >> b;

ff2.close();
AfxMessageBox(mycstring);

The a value is ok, the CString remains empty...

Upvotes: 0

Views: 625

Answers (2)

Jerry Coffin
Jerry Coffin

Reputation: 490128

You main problem is that when you read the string, the \n at the end of the first line is still in the input buffer. Since getline just reads up to the next \n in the input buffer, you get an empty string.

IMO, you'd be better off doing things a bit differently. To start with, instead of the explicit conversion with wcstombs_s, you'd be better off just using wofstream, which will handle the conversion automatically. You should also normally use [w]ifstream and [w]ofstream unless you're going to read and write via the same stream:

#include <fstream>
#include <string>
#include <windows.h>

int main() { 
    char name[] = "simtestagain.txt";
    std::wofstream ff(name);
    std::wstring my_string(L"Name with spaces");

    // avoid unnecessary flushes by using "\n" instead of std::endl;
    ff << 1 << "\n" << my_string << "\n" << 2 << "\n";

    ff.close();

    std::ifstream ff2(name);
    int a,b;
    char ignore;
    std::string my_second_string;

    ff2 >> a >> std::noskipws >> ignore;
    std::getline(ff2, my_second_string);
    ff2 >> b;

    MessageBox(NULL, my_second_string.c_str(), "", MB_OK);
    return 0;
}

Note, however, that this depends on the fact that the string you've written to the file as multi-byte characters really all get encoded as single-byte characters, so what you write from the std::wstring will read cleanly as a std::string. In this case that's correct, but in the general case it won't be. The only time it works is when the content was all basically plain-ASCII anyway (so there was essentially no reason to play with wide characters, conversions, etc.)

If you want to support wide characters, then what you write as wide characters you should read back in as wide characters. This also simplifies the file handling a bit -- you can read and write the data via the same stream:

#include <fstream>
#include <string>
#include <windows.h>

int main(){ 
    char name[] = "simtestagain.txt";
    std::wfstream ff(name);
    std::wstring my_string(L"Name with spaces");

    ff << 1 << "\n" << my_string << "\n" << 2 << "\n";

    ff.seekg(0);

    int a,b;
    wchar_t ignore;
    std::wstring my_second_string;

    ff >> a >> std::noskipws >> ignore;
    std::getline(ff, my_second_string);
    ff >> b;

    MessageBoxW(NULL, my_second_string.c_str(), L"", MB_OK);
    return 0;
}

Upvotes: 0

Mark Loeser
Mark Loeser

Reputation: 18627

The extraction operator does not consume the whitespace, so getline is just reading the whitespace that is left over on your first line. Try adding this before your call to getline:

ff2.ignore(255, '\n');

Upvotes: 1

Related Questions