0

I'm trying to use ofstream's open(...) to open a file for writing in C++. For some reason, if I use a char* or string built from a stringstream, it fails. In other words, my ofstream object's fail() function returns true (verified with a check and console messages). See below:

stringstream ss;
ss << DIRECTORY_PATH;
// note, DIRECTORY_PATH is a string literal with correctly escaped backslashes
ss << generateTimestamp();
// generateTimestamp() returns a timestamp as a formatted char*
ss << ".txt";

char * logPath = (char*)malloc(sizeof(char) * strlen(ss.str().c_str()) + 1);
strcpy(logPath, ss.str().c_str();

ofstream stream;
stream.open(logPath, ios::out | ios::app);

if (stream.fail())
    cout << "fail";

This prints 'fail' to console. I have verified using debugger that logPath actually points to the correct, expected string; and yes, if I do a cout<< just before the line with stream.open, it prints the correct path to console as well, e.g.:

C:\Logs\2015:01:15:18:34:10.txt

But open(...) still flips the fail state and I can not write to the file. However if I populate logPath with a string literal instead, e.g.

char * logPath = "c:\\logs\\log.txt";

Then it works. Further, obviously if I put a string literal with my path directly into the open(...) then it works.

This also fails when using the timestamp generator:

stream.open(ss.str().c_str(), ios::out | ios::app);

Why? How can I get a C string / char* out of a stringstream that an ofstream open(...) call can read? Note, this also results in a fail state:

stream.open(ss.str(), ios::out | ios::app);

Further, if I build a string using the append command, that fails as well. E.g.:

string path;
path.append(DIRECTORY_PATH);
path.append(generateTimestamp());
path.append(".txt");
stream.open(path, ios::out | ios::app);

This fails, but again, when I debug or print to console (e.g. cout << path) then I get the expected path:

C:\Logs\2015:01:15:18:34:10.txt

What am I missing?

Steverino
  • 2,099
  • 6
  • 26
  • 50
  • Check contents of logPath after copying in debugger. I suspect nul-terminating issues. – user3159253 Jan 15 '15 at 05:31
  • Are we not supposed to close the `stringstream` before using the `string`? – Jean-Baptiste Yunès Jan 15 '15 at 06:57
  • @user3159253 - Yes, I checked the contents. They appear correct to me. Just in case, I tried manually adding a null termination '\0' to the end of the path string as well, but that did not work either. – Steverino Jan 15 '15 at 19:27
  • @Jean-BaptisteYunès I have not heard that closing the stringstream was necessary, but I will try that for kicks. In the meantime, I have verified that using strcpy(...) to get the c_str out of the stringstream does yield the expected path; just that it does not work when I use that c_str to open the path. – Steverino Jan 15 '15 at 19:29
  • @jxh That did not solve the problem in my case, but your question, I think, has led me to the answer, which I am posting below forthwith. (It was a stupid problem, of course.) – Steverino Jan 15 '15 at 19:42

1 Answers1

2

Simple answer, my string was being generated by a function that included characters that are illegal in Windows file names, and I was overlooking it in my late night exhaustion.

Longer answer for posterity, part of the string I was using as my file path was being read in from a time stamp generation function that was returning colon ':' as part of the time stamp. The function was meant for console output, but I was trying to use it to generate file names. Windows, of course, does not allow colon ':' in file names.

Steverino
  • 2,099
  • 6
  • 26
  • 50
  • But this means your question provided false information. The actual code samples you display above would work fine for you. – jxh Jan 15 '15 at 21:31
  • You are right. I will edit the question to reflect what I was doing wrong originally. It had not occurred to me that using a different string path would result in a different result at the time I posted this. – Steverino Jan 16 '15 at 01:17
  • @jxh I am a bit new with posting to S.O., please let me know if I am taking the right action to improve my question, and if my correction to the question is suitable. – Steverino Jan 16 '15 at 01:25
  • I think it is clear what happened in your edited question. However, the primary problem was that when you tested using a string literal, you did not test the actual string that was stored in the `string` object. Your failure to identify the problem was a failure in test methodology, which is not a very interesting question, unfortunately. – jxh Jan 16 '15 at 01:29