ifstream not reading EOF character
First thing is first, you shouldn't check like that. eof()
doesn't return true
until after a failed read. But you can do better (and easier)!
check the stream state with the implicit conversion to void*
which can be used in a bool
context. Since most of the read operations on streams return a reference to the stream, you can write some very consice code like this:
std::string line;
while(std::getline(currentfile, line)) {
// process line
}
Basically what it is doing is saying "while I could successfully extract a line from currentfile
, do the following", which is what you really meant to say anyway ;-);
Like I said, this applies to most stream operations, so you can do things like this:
int x;
std::string y;
if(std::cin >> x >> y) {
// successfully read an integer and a string from cin!
}
EDIT: The way I would rewrite your code is like this:
string line;
unsigned long pos = 0;
int linenumber = 0;
ifstream curfile(input.c_str());
std::cout << "About to try to read the file" << std::endl;
while (std::getline(curfile, line)) {
std::cout << "Getting line " << linenumber << std::endl;
linenumber++;
// do the rest of the work with line
}
ifstream EOF executing early
It looks like you discard the data at the end of the file if the file size isn't an exact multiple of SIZE
.
Also, even if the file size is an exact multiple of SIZE
you'll be reading the last character and then eof()
will not return true
. Not until you've tried reading the next character will eof()
return true
, and that will trigger your error message, ERROR: EOF DETECTED
.
More on that here:
Why is iostream::eof()
inside a loop condition (i.e. while (!stream.eof())
) considered wrong?
An alternative approach:
unsigned i = 0;
while(my_file >> file_buffer[i]) { // loop for as long as extracting succeeds
if(++i == SIZE) {
sendData(client_socket, file_buffer, i); // add a size parameter
// memset(file_buffer, 0, sizeof file_buffer); // why waste the time?
i = 0;
}
}
if(i) sendData(client_socket, file_buffer, i); // send the last part in the buffer
How does ifstream's eof() work?
-1 is get
's way of saying you've reached the end of file. Compare it using the std::char_traits<char>::eof()
(or std::istream::traits_type::eof()
) - avoid -1, it's a magic number. (Although the other one is a bit verbose - you can always just call istream::eof
)
The EOF flag is only set once a read tries to read past the end of the file. If I have a 3 byte file, and I only read 3 bytes, EOF is false
, because I've not tried to read past the end of the file yet. While this seems confusing for files, which typically know their size, EOF is not known until a read is attempted on some devices, such as pipes and network sockets.
The second example works as inf >> foo
will always return inf
, with the side effect of attempt to read something and store it in foo
. inf
, in an if
or while
, will evaluate to true
if the file is "good": no errors, no EOF. Thus, when a read fails, inf
evaulates to false
, and your loop properly aborts. However, take this common error:
while(!inf.eof()) // EOF is false here
{
inf >> x; // read fails, EOF becomes true, x is not set
// use x // we use x, despite our read failing.
}
However, this:
while(inf >> x) // Attempt read into x, return false if it fails
{
// will only be entered if read succeeded.
}
Which is what we want.
why does ifstream read beyond eof? (even if no file is open) how to stop reading at eof?
why does ifstream read beyond eof?
I am sure it does not.
Are you asking why the bad()
is not true after you move beyond the end?
(even if no file is open) how to stop reading at eof?
If you attempt to read beyond the end of a file then you will get an error. Moving beyond the end by itself is not enough. But an attempt to access the data after you are beyond the end should cause an error.
Well you see to have a bug is here:
file.read(data,size); // can read outside file
for(int i=0; i<size; i++)std::cout<<data[i]; // PSModulePath=C:\Program Files\WindowsPowerShell\Modules;C:\Windows\...
This should be written as:
if (file.read(data, size)) {
// If you attempt to read and it works then you can print out
// the data you read otherwise what is the point.
// Also notice you can't gurantee that you got `size` bytes.
// You should consult `gcount()` to get the number of characters read.
for(int i = 0; i < file.gcount(); ++i) {
std::cout << data[i];
}
}
How to know if the next character is EOF in C++
istream::peek()
returns the constant EOF
(which is not guaranteed to be equal to -1) when it detects end-of-file or error. To check robustly for end-of-file, do this:
int c = file.peek();
if (c == EOF) {
if (file.eof())
// end of file
else
// error
} else {
// do something with 'c'
}
You should know that the underlying OS primitive, read(2)
, only signals EOF when you try to read past the end of the file. Therefore, file.eof()
will not be true when you have merely read up to the last character in the file. In other words, file.eof()
being false does not mean the next read operation will succeed.
Related Topics
Why Can't I Replace Std::Map with Std::Unordered_Map
Vscode G++ It Isn't Finding .Cpp Definition Files
C++ - Std::Thread Crashes Upon Execution
Shared_Ptr and Weak_Ptr Differences
Initialize a Vector to Zeros C++/C++11
Why Do We Need to Tie Std::Cin and Std::Cout
What Does Static_Assert Do, and What Would You Use It For
C++ Convert from Lpctstr to Const Char *
Uniform Initialization Fails to Copy When Object Has No Data Members
Timestamps for Embedded System
Undefined Symbol on a Template Operator Overloading Function
How Are Gcc and G++ Bootstrapped
Adding Multiple Executables in Cmake
Algorithm to Add or Subtract Days from a Date
Std::Pow Produce Different Result in 32 Bit and 64 Bit Application