I'm trying to write a long to a text file using c++ fstream class. The file is already created on disk before the execution. I run the following code and can read the initial value but can't save the new one, overwriting. What am i doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[]) {
long f;
fstream myFile("data.txt", fstream::in|fstream::out);
cout << "f before: " << f << endl;
myFile >> f;
cout << "f after: " << f << endl;
f++;
cout << "f after increment: " << f << endl;
myFile << f;
myFile.close();
return 0;
}
After that, I read the value in the file and it isn't changed. What I did wrong here?
You need to rewind to the beginning of the file before writing. Otherwise the second value is written after the first one.
You need to add myFile.seekp(ios::beg); just before myFile << f; in order to update the count correctly.
If you want to keep appending to the end, add myFile.clear(); before myFile << f;. This will cause the contents to become :
1->12->1213->12131214->1213121412131215. This is required because eof is reached upon reading the input. Note that get and put pointers are the same.
As you have yourself correctly pointed out, this is required because the file has just the number, not even the newline. Thus the read operation hits straight the EOF and causes problems. To work around it, we clear eof status and continue.
Adding a newline at the end is a solution as you suggested. In that case
myFile.seekp(ios::beg);
myFile << f<<"\n";
Would be the complete solution.
I figured what I was doing wrong here:
My file contained ONLY the long that I wanted to read and write afterwards. When I read the file, I reached EOF and then couldn't rewind or write anything at the end.
That said, my solution was to include a space or a \n at the end of the file.
Does anyone know why the API works this way? Does not seeem very useful for me...
It has to do with this line:
myFile >> f;
Remove it and everything works just fine. I'm not familiar with fstream but it seems to me this code would try to force a string in a long. I'm also not allowed to cast it to a long, which makes me think this is never meant to be executed like this. I suggest you read up on how to retrieve a value from a file as a long type and then try again.
edit:
After reading a bit this site suggested you have to close and reopen the file between reading and writing, I was amazed that actually fixed it. I can't help but wonder why though, I thought fstream was meant for reading OR writing OR both.... Anyway, here is your working code:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[]) {
long f;
fstream myFile("data.txt", fstream::in|fstream::out);
cout << "f before: " << f << endl;
myFile >> f;
cout << "f after: " << f << endl;
f++;
cout << "f after increment: " << f << endl;
myFile.close();
myFile.open("data.txt", fstream::in|fstream::out);
myFile << f;
myFile.close();
return 0;
}
Related
I've been trying to write a program to open a file in both read and write mode:
#include <fstream>
#include <iostream>
using namespace std;
int main(){
fstream obj;
obj.open("hello.txt",ios::in|ios::out);
if (!obj){
cout << "File not opened" <<endl;
return 1;
}
obj << "Hi How are you" ;
char c;
while (!obj.eof()){
obj.get(c);
cout << c;
}
obj.close();
return 0;
}
When I compile this program on Visual Studio Code on Windows, though the text "Hi how are you" is printed in the file, the contents of the file are not printed on my screen. Can someone tell me what might be the problem?
Resetting the position indicator with seekp to 0 helps, because both output and input indicators are set to the end of file after write operation (you can read them with tellp tellg).
obj << "Hi How are you" ;
obj.seekp(0);
char c;
while (!obj.eof()){
obj.get(c);
cout << c;
}
Considering avoiding using obj.eof(), you can e.g. read your file line by line:
std::string line;
std::getline(obj, line);
std::cout << line << std::endl;
or in the loop:
while (std::getline(obj, line)) // here std::basic_ios<CharT,Traits>::operator bool is used to check if operation succeeded
{
std::cout << line << std::endl;
}
You got two problems there: buffering and seek position.
Buffering:
When you write the text with obj << "Hi How are you, you just write it into the buffer and the text gets written into the file after flushing the buffer. You can adjust which buffer type you want to use. The easiest way is to write std::endl after your text if you use line buffering.
A better explaination is already here
Seek Position:
You are reading from the last position in your file. You have to manually change the read position to the first character in the file, then you are done.
I am a fairly novice programmer, taking a few courses in my second year of highschool, and I have ran into a few problems. So let's get on with it.
Long story short, I have learnt how to create files like:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
string Test;
ofstream file;
file.open("Cookies.txt");
if(file.is_open()){
file << "I have cookies! :3" << endl;
file.close();
}
else{
cout << "Error. No file has been created." << endl;
}
ifstream cookies;
cookies.open("Cookies.txt");
if(cookies.is_open()){
cout << cookies.rdbuf();
}
return 0;
}
But my question now is, how do I like "use" what is in this file? Like if I want to save variables, or import the "I have cookies! :3" to a string variable in the main program. Because it seems reasonable that it should be possible, I have just not found out how to yet.
Also, how do I delete files that I have created? Because something like
file.delete("Cookies.txt"); does not work at all.
Thank you for your answers in advance.
Best regards, Staggen.
You can read from a file in a similar manner to writing to it, using an ifstream (input filestream) instead of an ofstream (output filestream), and using the >> operator to read into variables. It does default to reading a single value at a time, and for strings that translates into "words":
So:
if (cookies.is_open())
{
std::string word;
while (cookies >> word) // read from the filestream into "line"
{
std::cout << "Read a word: " << line << std::endl;
}
}
This is a fairly good method for reading different data types.
To read the entire line, you can use std::getline() with the newline character as the delimiter:
if (cookies.is_open())
{
std::string line;
while (std::getline(cookies, line, '\n'))
{
std::cout << "Read a line: " << line << std::endl;
}
}
Deleting a file is an OS-level activity unrelated to reading/writing to files. The <cstdio> header includes std::remove() which will delete files.
#anderas is right; you should go through a tutorial on file I/O in order to learn or solidify the basics.
I'm a beginner C++ user and I have tried collaborating with my classmates and such but we haven't been able to find an answer to this question. Our instructor has provided us with a linker that runs the main function for us and provides a simple text file for us to read from, and for the time being the second const char* in the heading is unimportant, for now all I need is to read the data from the file const char* saifFile and display it on-screen. When I run my program I have found that it stops the reading early. And I understand that you may not be able to help because you do not have access to the linker, but any help would be much appreciated.
Here is all my code:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
const int DESC_SIZE = 37;
struct Item
{
int itemId;
char description[DESC_SIZE];
double cost, price;
};
int processFile(const char* saifFile, const char* raofFile)
{
fstream outFile, inFile;
Item Inventory;
inFile.open(saifFile, ios::in);
while (inFile)
{
inFile >> Inventory.itemId >> Inventory.cost >> Inventory.price;
inFile.getline(Inventory.description, DESC_SIZE);
cout << " " << Inventory.itemId << " " << setw(5) << Inventory.cost << " " << setw(5) << Inventory.price <<" " << Inventory.description << endl;
}
return 0;
}
Make sure that the data type you have set to receive from inFile matches the type that inFile reads. If not, you will get a stream error and that will cause your program to stop reading.
After every read, try to inFile.clear() and see if your program hangs or stops early. Alternatively, after each read try
if(inFile.fail())
{
cout << "Read error in file\n";
}
This may not be the answer, but I'd start debugging here.
Try changing the while statement to:
while(!inFile.eof())
And also make sure that you have stored the data in the file in proper order.
I think I should begin by saying that I've just installed linux(debian) in my pc and have zero foreknowledge about doing things in linux. This problem is probably due to some really simple thing.
The relevant part of the code is similar to this:
ifstream stockNames("names.txt");
while (!stockNames.eof())
{
string snline;
getline(stockNames,snline);
cout << snline << endl;
.
.
.
}
this should print the first line of the file 'names.txt'. Instead it prints an empty line. And when I try to use snline as an input in another function I get the error 'Segmentation Fault'. How should I modify my code to do this? Is there any difference in usage of the ifstream in linux? Cause in windows the code works just fine
I've written the simple code below
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
string dos = "names.txt";
ifstream stockNames(dos.c_str() );
string snline;
while (getline(stockNames,snline))
{
cout << snline << " ";
}
return 0;
}
content of names.txt is
ABC
DEFG
HBO
instead of showing those line, cout << snline produces nothing
One more update: I've written two more codes.
(1)
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
cout << "program has initiated" << endl;
ifstream stockNames("names.txt");
if( !stockNames )
cout << "unable to open" << endl;
string snline;
while (getline(stockNames,snline))
{
cout << snline << endl;
}
return 0;
}
Result is as I desired. First 'program has initiated', then ABC, DEFG, HBO in different lines. But when I change this part
cout << snline << endl;
as
cout << snline << " hey" << endl;
Then ABC DEFG HBO does not appear and instead the only output is " hey".
This is crazy, how can this be??
btw I tried to make a debug with ddd and when I check the variable snline, ddd prints the following line
(gdb) print snline
$2 = {static npos = 4294967295, _M_dataplus = {> = {<__gnu_cxx::new_allocator> = {}, }, _M_p = 0x804c1a4 "ABC\r"}}
new mini update: when I change the relevant line as "cout << snline << " " << endl;" what's printed out is ' BC' ' FGH' ' BO' in seperate lines. Why does << operator overwrites over snline??
First of all, your while loop is wrong, because the eof flag (or any other failure flag) is set after an attempt to read from the stream fails; that means, if the attempt to read fails using getline(), the loop doesn't immediately exit, instead the loop continues which is a serious bug with your code.
So write your loop as (an idiomatic way):
string snline;
while (getline(stockNames,snline))
{
cout << snline;
//..
}
std::getline returns istream&, which can be implicitly converted into boolean type. So if getline reads successfully, then the returned value converts to true and the loop will continue, or else it will convert to false and the loop will exit.
After the edit in your question, all I can say that you need to check the stream object before using it to read contents from the file. More specifically, you need to check if the stream has been initialized properly and it has indeed opened the input file (i.e names.txt), and is ready to read data from it.
So try doing this:
//...
ifstream stockNames(dos.c_str() );
if (!stockNames)
{
cout << "file couldn't open properly" << endl;
return 0;
}
string snline;
while (getline(stockNames,snline))
{
cout << snline << " ";
}
Now run this, and see what it prints.
You have a dos file which uses \r\n at the end of each line. Linux doesn't recognise \r as part of the line ending so it gets included in the snline string. \r causes the next thing printed to appear at the beginning of the line so " hey" overwrites the stock names you were expecting to see.
Try
cout << snline << " " << endl;
and you'll see what I mean
stockNames will not actually appear to reach "end of file" until it has tried to input something and received the EOF character. Therefore, you're going to want to re-write your loop as follows:
ifstream stockNames("names.txt");
string snline;
getline(stockNames,snline);
while (!stockNames.eof())
{
cout << snline << endl;
.
.
.
getline(stockNames,snline);
}
or much simply
ifstream stockNames("names.txt");
string snline;
while (getline(stockNames, snline))
{
cout << snline << endl;
.
.
.
}
To answer your question; no, there is no significant difference in how ifstream operates on Linux and Windows. Of course if you write bugged code (as the other two answers have pointed out) then you might run into problems, but I can't see how the eof bug would cause the problems you are describing.
I would concentrate on the part where you say that using snline causes a segmentation fault, that indicates a more serious issue. Could you post code that demonstrates that?
You aren't checking whether the stream opened properly.
std::ifstream stockNames("names.txt");
if (! stockNames) {
std::cerr << "Unable to open file 'names.tex'\n";
}
else {
// Do the rest of your stuff here.
}
Always check status. Don't just plow ahead and assume everything is OK.
BTW, using namespace std; is something you see in a lot of bad books that are trying to save a tiny amount of ink. Try to get out of this bad habit.
I'm at the time beginning the development of a simple hex editor(that only reads at the time). I want to substitute OA for "\n", I'm trying with this code:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int main() {
ifstream infile;
int crtchar = (int)infile.get();
infile.open("test.txt", ifstream::in);
while(infile.good())
{
if(crtchar != 0xA)
cout << hex << setfill('0') << setw(2) << crtchar << ":";
else
cout << endl;
}
cout << "\n=====================================\n";
infile.close();
return 0;
}
It compiles without errors, but when I try to execute it, I just got nothing:
C:\Documents and Settings\Nathan Campos\Desktop>hex
=====================================
C:\Documents and Settings\Nathan Campos\Desktop>
This is happening just after I've added the feature to substitute OA for \n, because before it was working very nice. What is wrong?
You realize that you are only reading a character once, and before even opening the file, at that?
Sigh. You try to read the file before you open it.
Shouldn't you first open(...) your file and then try to get() from it?
Also, shouldn't you do more get()'s inside your while loop
Put int crtchar = (int)infile.get(); inside a while(infile.good()) and give it a try.