File-Stream/ifstreamreadbufferandseekfileposition.htm">http://www.java2s.com/Tutorial/Cpp/0240_File-Stream/ifstreamreadbufferandseekfileposition.htm
this page is able to print content of a file twice using
file.seekg(0);
So I assume that seekg(0) puts the "cursor" (in java) to the beginning of the file, and this web site: http://www.cplusplus.com/doc/tutorial/files/ confirms me.
But when I do this to a file that contains (0\n0\n0\n):
while(getline(file,line)) {
CCLOG(line.c_str());
CCLOG("%d",(int)file.tellg());
}
file.seekg(0);
CCLOG("%d",(int)file.tellg());
while(getline(file,line)) {
CCLOG(line.c_str());
}
(I'm doing this in cocos2dx 2.2.2 by the way)
it prints:
0
2
0
4
0
6
-1
I don't know what I'm doing wrong. Please help
I'm not 100% sure what you're asking here (and what it has to do with Java), but if you're asking why resetting the file cursor to the beginning of the file does not work, then here's my answer:
Make sure you reset the error flags of file before you call seekg. So instead of just
file.seekg(0);
write
file.clear();
file.seekg(0);
That will successfully reset the file cursor to the beginning of the file. The reason for this is, that once you reach the end of the file, the EOF (end-of-file) flag will be set and seekg does not reset it.
The reason for the behaviour you are seeing is that, once you read to the end of the file, the eof() state flag will be set. Any attempt to read or position the file after that will trigger an error. The error resulting in a return code of ERROR, which is -1.
You can reset the state flags (all of them) using clear(). So the code should read
file.clear();
file.seekg(0);
Related
So i've read all the lines from a file thusly
while (getline(ifile,line))
{
// logic
}
Where ifile is an ifstream and line is a string
My problem is I now want to use getline over again, and seem to be unable to return to the beginning of the file, as running
cout << getline(ifile,line);
Will return 0
I've attempted to use:
ifile.seekg (0, ios::beg);
To no avail, it seems to have no effect. How do I go back to the start of the file?
Since you have reached (and attempted to read past) the end of the file, the eof and fail flags will be set. You need to clear them using ifile.clear – then try seeking:
ifile.clear();
ifile.seekg(0);
This is because the eof flag has been set on the stream - due to you reaching the end of the file. so you have to clear this as an additional step.
Eg
ifile.clear();
ifile.seekg (0, ios::beg);
FYI: In my case, the order DID matter, thus
clear
seek
otherwise the next getline operation failed (MSVC v120)
Is there is a way to read in from a file until the end of a line, then go to another function do something, then come back afterwards to read in from the same file BUT from where we stopped last time (not from the beginning of the file)?
If yes, please provide a snippets. Code makes more sense to me than words. Thanks
When opening a file for writing using std::fstream::open(), you have the options to set the file openmode as the second argument after the filename...
std::fstream file;
file.open("myfile.txt", ios_base::openmode::ate);
openmode::ate is the flag used to open the file with the input cursor positioned at eof.
http://www.cplusplus.com/reference/ios/ios_base/openmode/
http://www.cplusplus.com/reference/fstream/fstream/open/
http://www.cplusplus.com/reference/fstream/fstream/
So i've read all the lines from a file thusly
while (getline(ifile,line))
{
// logic
}
Where ifile is an ifstream and line is a string
My problem is I now want to use getline over again, and seem to be unable to return to the beginning of the file, as running
cout << getline(ifile,line);
Will return 0
I've attempted to use:
ifile.seekg (0, ios::beg);
To no avail, it seems to have no effect. How do I go back to the start of the file?
Since you have reached (and attempted to read past) the end of the file, the eof and fail flags will be set. You need to clear them using ifile.clear – then try seeking:
ifile.clear();
ifile.seekg(0);
This is because the eof flag has been set on the stream - due to you reaching the end of the file. so you have to clear this as an additional step.
Eg
ifile.clear();
ifile.seekg (0, ios::beg);
FYI: In my case, the order DID matter, thus
clear
seek
otherwise the next getline operation failed (MSVC v120)
void bot_manager_item::create_games()
{
games.clear();
std::ifstream paths_in("C:\\Users\\bill hank\\Documents\\bot_plugins\\directory_listing.txt", std::ios::in);
while (paths_in.good())
{
send_message("The path was good.");
char q[5000];
paths_in.getline(q, 5000);
send_message(q);
games.push_back(qanda(q));
}
paths_in.close();
}
The file I'm loading exists, what else might be wrong? paths_in.good keeps failing.
Edit: I figured it out. Wow am I annoyed by the answer to this. Basically Windows lets you say whether you want to show file extensions or not. This windows installation is set to say that the extension shouldn't be shown. So when I'm checking the file again and again I'm seeing: directory.txt and thinking that this means that everything is fine with the directory when in reality the filename was directory.txt.txt
If paths_in.good() keeps failing then it means that some of the stream error flags are set (badbit, eofbit or failbit).
eofbit - end of file was reached
badbit - error with the stream buffer such as memory shortage or an exception inside the stream buffer is cast
failbit - some other error beside eof was reached
In order to find out what happened, you need to check which errorbit is set first, and then find out more about the specific error, and what can cause it.
Out of curiosity, does this code output the contents of the file correctly? If this code works, then the problem is something else. If this code doesn't work, then that likely means that the file either isn't where you specified, or you don't have read permissions on it.
void bot_manager_item::create_games() {
std::ifstream paths_in("C:\\Users\\bill hank\\Documents\\bot_plugins\\directory_listing.txt");
char q[5000];
while (paths_in.getline(q, 5000)) {
std::cout << q << std::endl;
}
}
This code does a few minor things differently.
std::ios::in doesn't need to be explicitly specified for std::ifstream.
it doesn't use is_good, while that should be fine, you can just treat the std::ifstream as a bool which will be true when it is in a good state.
getline() returns a reference to the stream it operated on, so you can just put that whole line in the condition.
cosmetic, but no need to explicitly close the ifstream if it is about to go out of scope.
I've got a program that is tailing a growing file.
I'm trying to avoid grabbing a partial line from the file (e.g. reading before the line is completely written by the other process.) I know it's happening in my code, so I'm trying to catch it specifically.
Is there a sane way to do this?
Here's what I'm trying:
if (getline (stream, logbuffer))
{
if (stream.eof())
{
cout << "Partial line found!" << endl;
return false;
}
return true;
}
return false;
However, I can't easily reproduce the problem so I'm not sure I'm detecting it with this code. std::getline strips off newlines, so I can't check the buffer for a trailing newline. My log message (above) is NEVER tripping.
Is there some other way of trying to check what I want to detect? Is there a way to know if the last line I read hit EOF without finding a EOL character?
Thanks.
This will never be true:
if (getline (stream, logbuffer))
{
if (stream.eof())
{
/// will never get here
If getline() worked, the stream cannot be in an eof state. The eof() and related state tests only work on the results of a previous read operation such as getline()- they do not predict what the next read will do.
As far as I know, there is no way of doing what you want. However, if the other process writes a line at a time, the problems you say you are experiencing should be very rare (non -existent in my experience), depending to some extent on the OS you are are using. I suspect the problem lies elsewhere, probably in your code. Tailing a file is a very common thing to do, and one does not normally need to resort to special code to do it.
However, should you find you do need to read partial lines, the basic algorithm is as follows:
forever do
wait for file change
read all possible input using read or readsome (not getline)
chop input into lines and possible partial line
process as required
end
An istream object such as std::cin has a get function that stops reading when it gets to a newline without extracting it from the stream. You could then peek() or get() it to see if indeed it is a newline. The catch is that you have to know the maximum length of a line coming from the other application. Example (untested) code follows below:
char buf[81]; // assumes an 80-char line length + null char
memset(buf, 0, 81);
if (cin.get(buf, 81))
{
if (cin.peek() == EOF) // You ran out of data before hitting end of line
{
cout << "Partial line found!\n";
}
}
I have to take issue with one statement you made here:
However, I can't easily reproduce the problem so I'm not sure I'm detecting it with this code.
It seems like from what you said it would be extremely easy to replicate your problem, if it is what you said. You can easily create a text file in some text editor - just make sure that the last like ends in an EOF instead of going on to a new line. Then point your program at that file and see what results.
Even if the other program isn't done writing the file, in the file that's where the line ends, so there's no way to tell the difference other than waiting to see if the other program writes something new.
edit: If you just want to tell if the line ends in a newline or not, you could write your own getline function that reads until it hits a newline but doesn't strip it.