How to change EOL coding in txt files? - c++

I am writing in Visual Studio 2008 in C++ and I have problems with other libraries - they do not accept the line endings (EOL) I generate with my txt files.
How can I change that while writing a file with
std::ofstream myFile;
myFile.open("traindata.txt");
myFile << "stuff" << endl;
// or
//myFile << "stuff" << '\n';
myFile.close();
EDIT 2 :
Ok, I did a mistake in code : I was appending "0 " for every iteration so that I had whitespace before the EOL.
By bad. You guys have been right. Thanks for help.

Is it possible that you just don't want the \n to end of line sequence to happen? Open your file using std::ios_base::binary: this turns off precisely the conversion. ... and don't use std::endl unless you really want to flush the stream:
std::ofstream myFile("traindata.txt", std::ios_base::binary);
myFile << "stuff\n";
The close() is typically also unnecessary unless you want to check that it was successful.

You should open the file stream in binary mode to keep C++ library from converting line endings automatically:
myFile.open("traindata.txt", std::ios_base::out|std::ios_base::binary);
That will keep C++ library from converting '\n' to OS-specific EOL symbol (CR-LF on Windows).

Download notepad++ - that should be able to fix the problem.
Or dos2unix, unix2dos on cygwin

Use myfile << "\r\n" for the Windows-style ending, or myfile << "\n" for the UNIX-style.

Related

Problem in using seekg() to read file in C++

I am learning to read and write file in C++ and find a problem.
My test.txt file contains 3 string in 3 lines:
abc
def
mnp
My problem is: I don't understand why I need to use f.seekg(2, ios::cur);
instead of f.seekg(1, ios::cur);
I know how to use seekg() in c++ and I think that I just need to ignore 1 byte
to get the next line by the getline() function.
This is my code:
ifstream f;
f.open("D:\\test.txt", ios::in);
string str1, str2, str3;
f >> str1;
f.seekg(2, ios::cur);
getline(f, str2);
getline(f, str3);
cout << str1 << " " << str2 << " " << str3 << endl;
Reason for your trouble is explained for example here:
Why does std::getline() skip input after a formatted extraction?
However about your actual question about seekg. You open the file in text mode. This means that when you read the file, line feeds are given to your C++ code as single characters, '\n'. But on the disk they may be something else, and it seems you are running your code on Windows. There newline in a text file is typically two bytes, CR (ASCII code 13) and LF (ASCII code 10). Reading or writing in text mode will perform this conversion between a single character in your C++ string vs two bytes in the file for you.
seekg works on offsets and does not care about this, offsets are same whether you open the file in text or binary mode. If you use seekg to skip new line, your code becomes platform-dependent, on Windows you need to skip 2 bytes as explained above, while in other platforms such as Unix you need to skip just single byte.
So, do not use seekg for this purpose, see the linked question for better solutions.

C++ newline fails diff test?

So I have a two programs that I am comparing output to. Whenever it does a newline, it says my output is different using a diff utility.
I have tried using:
std::cout << endl;
and
std::cout << '\n';
but it winmerge still says that our output is different. I am running both executables on the same machine.
Streaming std::endl is equivalent to streaming '\n' then std::flush so, no, you won't see any differences. More likely your tool is expecting to find a Windows-style line ending (that is, CRLF rather than just LF).
std::cout << "\r\n" << std::flush;
But, instead of guessing, you should simply open up that comparison data in a hex editor and see for yourself what characters are expected.
Read the file in binary mode and check the byte values for the newline.
One will probably be a char with ASCII code 10
and the other will be 10 and 13.

C++ std::stringstream/ostringstream and UTF characters

I'm writing a program which processes some data, outputs it to a .csv file, then writes a GNUplot script, and calls GNUplot to execute the script and create an image file all with the same name (only different extensions). The filenames contain UTF characters (UTF-8 I believe?) such as °, φ and θ. All of this works perfectly fine when I compile and execute it in Linux with g++ 4.4.7. I then altered my code to compile in Microsoft Visual Studio 2008, and the problems start when I run the program.
I use the following two bits of code to
Make a standard filename string (to which I just add extensions for the various files)
Open a stream to write to a file (the only difference between the GNUplot script and the .csv files is the extensions
// Generate a file name string
stringstream ss;
ss << type << " Graph #" << gID << " - " << title;
string fileName = ss.str();
// Open a stream for the output file
ostringstream outfile;
outfile << fileName << ".gplt" << ends;
ofstream ofs( outfile.str().c_str() );
The contents of the ofstream files where ofs writes contain the UTF characters properly, however the stringstream-created string fileName and the ostringstream created filename (even when not created with fileName, I tested it) show the characters incorrectly.
Example:
What it should be - CDFvsRd Graph #32 - MWIR # 300m, no-sun, 30kts, θ=all°.csv
What it ends up as - CDFvsRd Graph #32 - MWIR # 300m, no-sun, 30kts, Ï=allË.csv
What can I do to remedy this, with as much standard C++ as possible? Would converting my fileName string to wstring help?
The solution was to write the Windows portion of the code to not export the filenames without the graph titles, omitting the UTF-8 characters from the filename. This wasn't a true solution, only a workaround.

C++ - ofstream doesn't output to file until I close the program

I have the following code:
ofstream mOutFile.open(logPath, ios_base::app);
string lBuilder;
lBuilder.append("========================================================\n");
lBuilder.append("Date: ");
lBuilder.append(asctime(timeinfo));
lBuilder.append("\n");
lBuilder.append("Log Message:\n");
lBuilder.append(toLog);
lBuilder.append("\n");
lBuilder.append("========================================================\n\n");
int lSize = lBuilder.size();
char* lBuffer = new char[lSize];
int index = 0;
for each (char c in lBuilder)
lBuffer[index++] = c;
mOutFile.write(lBuffer, lSize);
mOutFile.flush();
Unfortunately, until I close the app (I assume that closing the ofstream would work as well) the output does not get written to the text file. I know I could probably close and reopen the stream and everything will "just work" but that seems like a silly and incorrect solution. What am I doing wrong here?
I have also tried the following variations based on other questions I have found here, but these solutions did not work:
mOutputFile << flush;
mOutputFile << endl;
Thanks in advance for any assistance on this.
edit Everything in this code is working visual c++, it builds and works fine except the file is not written to until the stream is closed, even if I force a flush. Also, I switched from using the << operator to the char * and .write () to see if anything behaved differently.
std::ofstream file(logPath, ios_base::app);
file << "========================================================\n"
<< "Date: " << asctime(timeinfo)
<< "\nLog Message:\n" << toLog
<< "\n========================================================\n\n"
<< std::flush;
//if you want to force it write to the file it will also flush when the the file object is destroyed
//file will close itself
This is not only easier to read but it will probably also be faster than your method + it is a more standard appraoch
I ended up just "making it work" by closing and reopening the stream after the write operation.
mOutputFile << "all of my text" << endl;
mOutputFile.close();
mOutputFile.open(mLogPath);
EDIT After trying out forcing the flush on a few other systems, it looks like something just isn't performing correctly on my development machine. Not good news but at least the above solution seems to work when programmatically flushing the ofstream fails. I am not sure of the implications of the above code though, so if anyone wants to chime in if there are implications of closing and reopening the stream like this.
You can perform the following steps to validate some assumptions:
1.) After flush(), the changes to the file should be visible to your application. Open the file as std::fstream instead of std::ofstream. After flushing, reset the file pointer to the beginning and read the contents of the file. Your newly written record should be there. If not, you probably have a memory corruption somewhere in your code.
2.) Open the same file in an std::ifstream after your call to flush(). Then read the contents of the file. Your newly written record should be there. If not, then there's probably another process interfering with your file.
If both works, then you may want to read up on "file locking" and "inter-process syncronization". The OS can (theoretically) take as much time as it wants to make file changes visible to other processes.

Problem with iostream, my output endl are littles squares

I have a problem with with my output when I write to I file I get squares when I put endl to change lines.
std::ofstream outfile (a_szFilename, std::ofstream::binary);
outfile<<"["<<TEST<<"]"<<std::endl;
I get something like this in my file plus the other outputs don't write on the next line but on the same one.
[TEST]square
apparently I can't write the square here, but is it something about the ofstream being binary or something?
You don't really want to open the file in binary mode in this case.
Try this instead:
std::ofstream outfile (a_szFilename);
outfile<<"["<<TEST<<"]"<<std::endl;
You're opening the file in binary mode. in this case the endl is written as \n while a newline on windows is supposed to be \r\n
To open you file in text mode just don't include the binary flag the translation will be done automatically
std::ofstream outfile(a_szFilename);
outfile<<"["<<TEST<<"]"<<std::endl;
It's probably because you're in binary mode and the line endings are wrong. std::endl will place '\n' on the stream before flushing. In text mode, this will be converted to the correct line ending for your platform. In binary mode, no such conversions take place.
If you're on Windows, your code will have a line feed (LF), but Windows also requires a carriage return (CF) first, which is '\r'. That is, it wants "\r\n", not just a newline.
Your fix is to open the file in text mode. Binary files are not suppose to be outputting newlines or formatted output, which is why you don't want to use the extraction and insertion operators.
If you really want to use binary, then treat your file like a binary file and don't expect it to display properly. Binary and formatted output do not go hand in hand. From your usage, it seems you should be opening in text mode.