I am trying to read from file using fstream .The file I am trying
to read has this content:
1200
1000
980
890
760
My code:
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
fstream file("highscores.txt", ios::in | ios::out);
if (!file.is_open())
{
cout << "Could not open file!" << endl;
return 0;
}
int cur_score;
while (!file.eof())
{
file >> cur_score;
cout << file.tellg() << endl;
}
}
The output is:
9
14
18
22
26
Why after first read the tellg() returns 9,
the first read is the number (1200) which is 4 positions
and I know there is \r and \n so this make 6 positions. Also. if I add more number in my file tellg() will
return a bigger number after first read.
If you've saved your file in UTF8 with a text editor, there might be an UTF8 BOM at the beginning of the file. This BOM is 3 chars long, so added to the 6, it would make 9.
If you want to be sure, check out the beginning of the file, with:
fstream file("highscores.txt", ios::in | ios::out | ios::binary);
if(file) {
char verify[16];
file.read(verify, sizeof(verify));
int rd = file.gcount();
for(int i = 0; i<rd; i++) {
cout << hex << setw(2) << (int)verify[i] << " ";
}
cout <<dec << endl;
}
Edit:
Running on windows with MSVC2013 on the file and I found 4, 10, 15, 20, 25 as expected, and I couldn't reproduce your figures.
I've now done a test with mingw and here I get exactly your numbers, and the strange effect that increasing the number of lines increases the output.
THIS IS A BUG of MINGW when you read your windows (CRLF line separator) file in text mode:
If I save the file in UNIX style (i.e. LF line separator), I get with the same programme 4,9,13,17 which is again the expected value for a linux system.
If I save the file in WINDOWS style (i.e. CRLF line separator), and if I change the code to open the file in ios::binary, I get the awaited 4,10,15,20,25.
Apparently it's an old problem.
Related
I know that the default file open mode is out. And I think out will overwrite the data in the file, but in the following code, it age data doesn’t overwrite name data.
#include <fstream>
#include <iostream>
using namespace std;
int main () {
char data[100];
// open a file in write mode.
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// write inputted data into the file.
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// again write inputted data into the file.
outfile << data << endl;
// close the opened file.
outfile.close();
// open a file in read mode.
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// write the data at the screen.
cout << data << endl;
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
// close the opened file.
infile.close();
return 0;
Then I’m confused about the three open mode for file – app, out, trunc.
If for name I enter “Zara” and age “9”, the output should be “9ara”. However, it is not. It is “Zara 9”.
ios::out is the default mode for std::ofstream, it means that output operations can be used (i.e. you can write to the file).
ios::app (short for append) means that instead of overwriting the file from the beginning, all output operations are done at the end of the file. This is only meaningful if the file is also open for output.
ios::trunc (short for truncate) means that when the file is opened, the old contents are immediately removed. Again, this is only meaningful if the file is also open for output.
Your code just uses the default ios::out mode. So it starts writing from the beginning of the file, but doesn't remove the old contents. So the new contents will overlay what's already there -- if the file is originally 10 bytes long, and you write 3 bytes, the result will be the 3 bytes you write followed by the remaining 7 bytes of the original contents. More concretely, if the file originally contains:
Firstname Lastname
30
and you write FN LN and then 20 (with newlines after each), the resulting file will look like:
FN LN
20
Lastname
30
because you only overwrite the first 9 bytes of the file (assuming Unix-style newlines).
Once you've opened the file, all outputs to the file are written sequentially after each other, unless you use outfile.seekp() to go to a different location. It doesn't go back to the beginning of the file for each thing you write. seekp() has no effect if the ios::app is used; then every write goes at the end of the file.
Just a little correction to Barmar's answer. I think that the type ofstream implies not only the ios::out, but also the ios::trunc (and I'm not sure, but the ios::out could also imply the ios::trunc).
Here's the concrete example:
ofstream fich;
fich.open("archivo.txt");
for (unsigned i = 0; i < ag.n_pers && !fich.fail(); ++i) {
escribir_persona(fich, ag.pers[i]);
}
if (fich.fail()) {
ok = ERROR;
}
else {
ok = OK;
}
fich.close();
When I call this function, the data of the file is completely overwrited (even if the data to write is less than that which was writen previously), and if the data to write is empty, this just deletes everything in the file.
I tried to access the next characters to be read from the file using tellg() and returns the position correctly if the file has one line of text.. But when the file has more than one line it gives me some abnormal values.. I am attaching my code and the output i got below..
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char temp;
ifstream ifile("C:\\Users\\admin\\Desktop\\hello.txt");
ifile>>noskipws;
while(ifile>>temp)
{
cout<<temp<<" "<<ifile.tellg()<<endl;
}
}
output:
H 3
e 4
l 5
l 6
o 7
8
W 9
o 10
r 11
l 12
d 13
. 14
. 15
16
! 17
! 18
! 19
File : Hello.txt contains 3 lines as given below..
Hello
World
!!!
Don't understand why it starts with 3 in the print statement which should instead start from 1.. when there are 2 lines it starts printing from 2..
can anyone explain me..?
As a matter of fact tellg() is not to return the offset of a byte in a stream, but a pos_type descriptor which is reusable by seekg(). It will match the byte offset if the file is binary, but it is not guaranteed in a text stream. (In a *ix it will match too, but in Windows there is no direct assignment.)
Open the file in binary mode, because seekg() is used with an offset. If the modification of the file happens between two runs of your program, you'll need to store positionEof in a file.
Note: In binary mode you could actually store positionEof in an integer, but I prefer using the explicite type as long as it is possible.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
streampos positionEof;
// Record original eof position.
ifstream instream("C:\\Users\\istvan\\Desktop\\hello.txt", ios::in | ios::binary);
if (instream.is_open()) {
instream.seekg(0, ios::end);
positionEof = instream.tellg(); // store the end-of-file position
instream.close();
}
else
cout << "Record eof position: file open error" << endl;
// Append something to the file to simulate the modification.
ofstream outstream("C:\\Users\\istvan\\Desktop\\hello.txt", ios::app);
if (outstream.is_open()) {
cout << "write" << endl;
outstream << "appended text";
outstream.close();
}
// Check what was appended.
instream.open("C:\\Users\\istvan\\Desktop\\hello.txt", ios::in | ios::binary);
if (instream.is_open()) {
instream.seekg(positionEof); // Set the read position to the previous eof
char c;
while ( instream.get(c))
cout << c;
instream.close();
}
else
cout << "Check modification: file open error!" << endl;
return 0;
}
pardon my code formatting as I have just started out in C++.
Anyway, I am trying to read and display the contents (in the form of matrix) from a text file.
While I am able to read in the file, instead of displaying the outputs as how it should be as in its text file, I am getting the contents all in a single line. I can't brute force the code as I have several file where its matrix is different.
Eg. matrix01
9 7 6
8 -1 0
Or matrix02
2 10
3 5
-7 25
The following code is the my file input, and so what can I do to make it out in rows and columns instead of a single row/line?
#include <iostream>
#include <fstream>
using namespace std;
int main(){
ifstream fin; //file input stream
ofstream fout; //file output stream
fin.open("/Desktop/matrix_a.txt");
fout.open("/Desktop/matrix_a.out");
string msg;
while (fin>>msg){//read until eof
cout << msg << " ";
}
fin.close();
fout.close();
}
You state:
I am getting the contents all in a single line.
Your code does the following:
while (fin>>msg){//read until eof
cout << "" << msg << " ";
}
This is because you do not write a std::endl to std::cout, here, and you do not end up printing a newline at any time. operator<< does not automatically add a newline at the end of the statement. It is your responsibility to do, if so desired.
I'm trying to generate a text file that has 50 lines, each line consisting of 50 spaces. However, every few lines, 9 or 10 extra bytes gets added to the file.
#include <iostream>
#include <fstream>
using namespace std;
void InitializeCanvas() {
ofstream file("paint.txt");
int b = 0;
for (int i = 0; i < 50; i++) {
for (int j = 0; j < 50; j++) {
file << " ";
}
file << "\r\n";
//these lines show where the pointer is and where it should be
b += 52;
int pointer = file.tellp();
int difference = pointer - b;
cout << pointer << " (" << (difference) << ")" << endl;
}
file.close();
}
int main() {
InitializeCanvas();
return 0;
}
On line 9, 9 extra bytes are added. On lines 19, there are 19 extra bytes. Same for 29, 39, and 49. No extra bytes are added except for on those lines. What could be causing that? This code was compiled using CodeBlocks 13.12.
Edit: Since the question got some additional information, the explanation of this answer does not fit anymore completely - still the solution should work.
The extra bytes come from two mixed newlines per row (NL+CRLF). Let's take a look at the end of a line because \n is interpreted already\r\n in your compiler.
... 20 0D 0D 0A
... Space NL CR LF
The solution is in the constructor of ofstream. It's in text mode.
explicit ofstream (const char* filename, ios_base::openmode mode = ios_base::out);
Just use \n or write your data in binary format, or use endl.
ofstream file("paint.txt", std::ios_base::binary | std::ios_base::out);
Some (windows) compilers replace "\n" by "\r\n" so if you write "\r\n" you get the '\r' twice.
All you need to do is to use endl instead of the "\r\n"
replace this line:
file << "\r\n";
by:
file << endl;
I am trying to read from binary file on UNIX. The file exists and has several data information in it.
The code looks like this:
fstrean fstrHandler;
string strFileName;
char Buf[30000];
fstrHandler.open(strFileName.c_str(), ios::in | ios::binary);
fstrHandler.seekp(0, std::ios_base::beg);
std::cout<< "Posi before read= "<< fstrHandler.tellg()<<endl; //*** Show after running 0
fstrHandler.read (Buf, 400);
std::cout<< "Posi after read= "<< fstrHandler.tellg()<<endl; //*** Show after running 0
std::cout<< " gcount ()= "<< fstrHandler.gcount ()<< << endl; //*** Show after running 0
if (fstrHandler.eof ()) {
fstrHandler.clear();
}
After the read I get that the position in file is still zero zero, but the file is not empty.
Try seekg rather than seekp, and is there 400 bytes in the file? this appears to work okay for me, if you input a file that contains more than 400 bytes. If less, then the tellg after read reports -1, but gcount() is correct.
Also, after opening the file - test to see if the file was indeed opened e.g.
if (fstrHandler)
{
// do stuff
}
else
std::cerr << "foo bar" << std::endl;