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.
Related
Please can anybody help me? I'm a beginner and I have a hard assignment.
I need to write a c++ program that does the following :
Ask the user to enter two text file , the the first one contains a list of words in one column Regardless of their number , second one contains the text file ,like this:
//output
Enter the keywords file: keywords_file.txt
Enter the text file: text_file.txt
2.Search for the keywords from the keywords file in the text file
3.if the keyword exist the output =1 "true", if the keyword doesn't exist output =0 "false" ,like this :
system : 1 //its exist
book : 0 //its doesn't exist
Then output in new text file (ofstream)
I put the words in file each one on its own line because some of them are phrases I don't want to sprit them ,search them as one word , also the test file I want it to stay as complete text not separate words from each other so possibly I cant use "map" & "vector". I already tried them...so possibly I can consider that each word in the words file just a line and read them all , then search for them in the text file
i found this code here in the site but its need modifications , could any body help me ?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
bool CheckWord(char* filename, char* search)
{
int offset;
string line;
ifstream Myfile;
Myfile.open (filename);
if (Myfile.is_open())
{
while (!Myfile.eof())
{
getline(Myfile,line);
if ((offset = line.find(search, 0)) != string::npos)
{
cout << "found '" << search << "' in '" << line << "'" << endl;
Myfile.close();
return true;
}
else
{
cout << "Not found" << endl;
}
}
Myfile.close();
}
else
cout << "Unable to open this file." << endl;
return false;
}
int main ()
{
CheckWord("dictionary.txt", "need");
return 0;
}
The code that you found somewhere is really bad. You should not use it. Let me explain you why.
Most important, it does not fulfill any of your requirments. So, it is completely wrong for your purpose
There are design-, syntax- and semantic errors. It does not even compile on my machine
Examples: Do not use using namespace std; always use fully qualified names like std::string
Type of vearibe offset should be size_t. You compare it later to string::npos. So, type is wrong
The constructor of std::ifstream can open the file for you. So the call to open is not necessary
MyFile is not a class name. it should start with a lowercase character
Using is_open is not necessary. The bool operator for the iostreams is overloaded. So, you can simply write if (myFile)
while (!Myfile.eof()) is a semantic bug. It will not work as you think. Please find many many examples here on SO. Please write instead while (std::getline(myFile, line))
Explicit call to close is not necessary. The destructor of the stream will automatically close the file for you
Function should haveonly one exit point. There are 2 return statements.
cout << "Not found" << endl; can be replaced by std::cout << "Not found\n". But better would be to mention, what has been "not found"
Do not use char* for strings. Always use std::string instead.
Write many many comments and use meaningful variable names
You see. You should not use this code. It is really bad.
Then, next step, before you start any coding, you should anaylyse the requirements and then design a solution
So, obviously, you need to open 2 input files and one output files. If any of this open activities fail, then no need to open any other file. So, Let us do this sequentially. Open, check, if ok, then open next.
Then, because you want to compare words from a list to the contents of a complete text file, we should first and only once read the comlete text file. Then, we will read keyword by keyword and check, if it is in the text file data.
The we seacrh for the keyword and will show the result in the output file and, for debug purposes, also on std::cout.
Since you are new and have maybe restrictions regarding the usage of modern C++ and espcially the usage of the C++ STL, I will use simple C++ code.
Please see the following simple example.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
int main() {
// Give instructions to the user to enter the file name for the keywords file
std::cout << "Please enter the file name for the keywords file:\t ";
// Read the filename for the keywords file
std::string keywordFileNname;
std::cin >> keywordFileNname;
// Open the keywords file for reading
std::ifstream keyWordFileStream(keywordFileNname);
// Check, if that worked and continue only if OK
if (keyWordFileStream) {
// Next, we ant to have the text file name. Instruct use to give the filename for the text file
std::cout << "Please enter the file name for the text file: \t ";
// Read the file name of the text file
std::string textFileName;
std::cin >> textFileName;
// Open the text file for reading
std::ifstream textFileStream(textFileName);
// Check, if the text file could be opened and continue only, of OK
if (textFileStream) {
// Now, give instructions to the user to open the output file name
std::cout << "Please enter the file name for the output file: \t ";
// Read the filename for the output file
std::string outputFileName;
std::cin >> outputFileName;
// Open the output file stream
std::ofstream outputFileStream(outputFileName);
// Check, if the output file could be opened, If OK, continue
if (outputFileStream) {
// So, all files are open, we can start to work
// We will read the complete text file in one string
// This solution is not very good, but avoids more complex features
std::string textFileData;
char oneCHaracter;
while (textFileStream.get(oneCHaracter)) {
textFileData += oneCHaracter;
}
// So, now all text file has been read to one string.
// Next we will read keyword by keyowrd and search it in the text file
std::string keyWord;
while (keyWordFileStream >> keyWord) {
int exists = 0;
// Check, if the keyword is in the text file data
if (textFileData.find(keyWord) != std::string::npos) {
// Keyword found
exists = 1;
}
// Write result to output file
outputFileStream << std::right << std::setw(50) << keyWord << std::left << " --> " << exists << '\n';
// And write some debug output. You may delete this line if not needed
std::cout << std::right << std::setw(50) << keyWord << std::left << " --> " << exists << '\n';
}
}
else {
// output file could not be opened. Show error message
std::cerr << "\nError: Could not open output file '" << outputFileName << "'\n\n";
}
}
else {
// text file could not be opened. Show error message
std::cerr << "\nError: Could not open text file '" << textFileName << "'\n\n";
}
}
else {
// Keyword file could not be opened. Show error message
std::cerr << "\nError: Could not open key word file '" << keywordFileNname << "'\n\n";
}
return 0;
}
You can see that I always check the result of IO operations. That is very important.
There is of course also a more advanced and more modern C++ solution. To concentrate more on the essential task, I put all the file handling stuff in a separate function.
This example code uses C++17. So you must enable C++17 for your compiler. Please see (one of many possible solutions)
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <vector>
#include <iterator>
#include <algorithm>
// In order to concentrate on the essential task, we put the file stream stuff in a separate function
bool getValidStream(std::ifstream& keyFileStream, std::ifstream& textFileStream, std::ofstream& outFileStream) {
// We are pessimistic and assume an error
bool result{ false };
// Give instructions to the user to enter the file name for the keywords file
if (std::cout << "Please enter the file name for the keywords file:\t ")
// Read keyword text filename
if (std::string keywordFileNname{}; std::cin >> keywordFileNname)
// Open key word file
if (keyFileStream.open(keywordFileNname); keyFileStream)
// Give instructions to the user to enter the file name for the text file
if (std::cout << "Please enter the file name for the text file: \t ")
// Read text filename
if (std::string textFileName{}; std::cin >> textFileName)
// Open text file
if (textFileStream.open(textFileName); textFileStream)
// Give instructions to the user to enter the file name for the output file
if (std::cout << "Please enter the file name for the output file: \t ")
// Read output filename
if (std::string outFileName{}; std::cin >> outFileName)
// Open output file
if (outFileStream.open(outFileName); outFileStream)
result = true;
if (not result)
std::cerr << "\nError: Problems with files\n\n";
return result;
}
int main() {
// Define streams to use in our software
std::ifstream keyWordFileStream{}, textFileStream{};
std::ofstream outputFileStream{};
// Get valid streams
if (getValidStream(keyWordFileStream, textFileStream, outputFileStream)) {
// Read all keywords into a vector
std::vector keywords(std::istream_iterator<std::string>(keyWordFileStream),{});
// Read complete textfile into a string variable
std::string textData(std::istreambuf_iterator<char>(textFileStream), {});
// Output result
std::transform(keywords.begin(), keywords.end(), std::ostream_iterator<std::string>(outputFileStream, "\n"),
[&](const std::string& key) {return (textData.find(key) != std::string::npos) ? key + ": 1" : key + ": 0"; });
}
return 0;
}
The code you have shown is almost workable. The core logic of finding the search string in the line read from the file using find is what you would want to do. If you find it, return true. That's certainly one way of going about the problem you describe.
Read on why !Myfile.eof() is bad, fix it.
Remove close() calls since the destructor of std::basic_ifstream release the underlying file resource
You're passing in character literals but your function signature is bool CheckWord(char* , char* ). Fix that source of warning.
Once, you've fixed all this, you should be fine. You have the core logic of finding words in a file. I still don't get why you asked the question when you've got a near working solution. If you're looking for complexity gains etc. you need to explore the data structure to be used, but then that's probably not your intention for this assignment.
New in C++ and I am trying to copy the values that I read on my console after opening a .csv file to another .csv file that I want to create. Unfortunately it copies only the last value, not the whole. Any help? thanks very much!
int main()
{
ifstream filetocopy("ecommerce.csv");
int d;
while(filetocopy>>d){
cout << d << endl;}
ofstream numbers("testing.csv");
numbers << d << endl;
}
Obvious problems with your approach:
1) You create the output file after you read the entire input file which means you write only the last value to the output file.
2) Even if you fix 1) you would still write the csv values in a wrong order to the output file. Suggestion: read line by line -> print the line on the console -> write the line to the file.
Here's a simple solution to your problem (just an example you can improve it):
#include <iostream>
#include <fstream>
#include <string>
int main () {
std::ifstream filetocopy("ecommerce.csv");
std::ofstream numbers("testing.csv");
std::string line;
while(std::getline(filetocopy, line)) {
std::cout << line << std::endl;
numbers << line << std::endl;
}
return 0;
}
You have two problems here.
First, you didn't create the ofstream to output until after you had already used and discarded most of your data.
Second, in the while loop, all you did was write your data to the standard output and not to file.
To correct the problem, you need to move the ofstream initialization before the while loop and move numbers << d << endl; into the loop.
Think of your ifstream as like an old VCR tape. As you are printing out characters with that while loop
while(filetocopy>>d){
cout << d << endl;}
your ifstream finished "playing". Every loop d gets a new frame of the tape and prints it out. So the tapehead is at the end, and now d is just holding onto the last frame of the credits. So when you write it to your new csv, that's the only value it has left.
Try not printing out all those values first.
I have some code here
https://github.com/Fallauthy/Projects/blob/master/cPlusPlusProjects/bazaPracownikow/bazaPracownikow/bazaPracownikow/main.cpp
And I have no idea how to show contents in my file. I mean i know how, but it doesn't show same I Have in file (in link). It show in next line. This code is responsible to load file
while (!baseFile.eof()) {
//wczytaj zawartosc pliku do zmiennej
std::string buffer;
baseFile >> buffer;
//wypisz
loadLineFromBase += buffer;
loadLineFromBase += " \n";
}
std::cout << loadLineFromBase << std::endl;
Unless I see all your code all I can do for you is give you a sample in return, I don't know what you're trying to do but it seems in this case you're looking for this.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string Display = "";
ofstream FileOut;
ifstream FileInput;
FileOut.open("C:\\Example.txt");
FileOut << "This is some example text that will be written to the file!";
FileOut.close();
FileInput.open("C:\\Example.txt");
if (!FileInput)
{
cout << "Error File not Found: " << endl;
return 1;
}
while (!FileInput.eof())
{
getline(FileInput, Display);
}
FileInput.close();
cout << Display << endl;
return 0;
}
Simply put if you're currently working wit ha text document
use getline()
When you use getline() it takes two arguments the first will be in this case your ifstream object, as in what you're using to open the file. The second will be the string you're using to store the contents in.
Using the method I outlined above you'll be able to read the entire file contents.
And please next time as it was said above outline your problem more in depth and if you provide us with all of your code we may better assist you!
Your snippet of code automatically add a newline to every string read from the input file, even if originally those were words separeted by spaces. Probably you want to keep the structure of the original file, so it's better to read one line at a time and, unless you need it for some other uses, print it out in the same loop.
std::string buffer;
// read every line of baseFile till EOF
while ( std::getline(baseFile, buffer) ) {
std::cout << buffer << '\n';
}
Edit: changed my question to be more accurate of the situation
I'm trying to open up a text file (create it if it doesnt exist,open it if it doesnt). It is the same input file as output.
ofstream oFile("goalsFile.txt");
fstream iFile("goalsFile.txt");
string goalsText;
string tempBuffer;
//int fileLength = 0;
bool empty = false;
if (oFile.is_open())
{
if (iFile.is_open())
{
iFile >> tempBuffer;
iFile.seekg(0, iFile.end);
size_t fileLength = iFile.tellg();
iFile.seekg(0, iFile.beg);
if (fileLength == 0)
{
cout << "Set a new goal\n" << "Goal Name:"; //if I end debugging her the file ends up being empty
getline(cin, goalSet);
oFile << goalSet;
oFile << ";";
cout << endl;
cout << "Goal Cost:";
getline(cin, tempBuffer);
goalCost = stoi(tempBuffer);
oFile << goalCost;
cout << endl;
}
}
}
Couple of issues. For one, if the file exist and has text within it, it still goes into the if loop that would normally ask me to set a new goal. I can't seem to figure out what's happening here.
The problem is simply that you are using buffered IO streams. Despite the fact that they reference the same file underneath, they have completely separate buffers.
// open the file for writing and erase existing contents.
std::ostream out(filename);
// open the now empty file for reading.
std::istream in(filename);
// write to out's buffer
out << "hello";
At this point, "hello" may not have been written to disk, the only guarantee is that it's in the output buffer of out. To force it to be written to disk you could use
out << std::endl; // new line + flush
out << std::flush; // just a flush
that means that we've committed our output to disk, but the input buffer is still untouched at this point, and so the file still appears to be empty.
In order for your input file to see what you've written to the output file, you'd need to use sync.
#include <iostream>
#include <fstream>
#include <string>
static const char* filename = "testfile.txt";
int main()
{
std::string hello;
{
std::ofstream out(filename);
std::ifstream in(filename);
out << "hello\n";
in >> hello;
std::cout << "unsync'd read got '" << hello << "'\n";
}
{
std::ofstream out(filename);
std::ifstream in(filename);
out << "hello\n";
out << std::flush;
in.sync();
in >> hello;
std::cout << "sync'd read got '" << hello << "'\n";
}
}
The next problem you'll run into trying to do this with buffered streams is the need to clear() the eof bit on the input stream every time more data is written to the file...
Try Boost::FileSystem::is_empty which test if your file is empty. I read somewhere that using fstream's is not a good way to test empty files.
i am new to this site , and this my first question !
i have a question about fstream function .
fstream f("new.dat",ios::out|ios::in);
fstream is for both input and output , so when we use it like this , and there is a new.dat file before it will output and input both . but it is strange , when i do that , it will output data correctly , but it is unable to input .
i found out if you close it , and reopen it , it will input . why it is like that??
int main()
{
fstream writeFile("newFile.dat", ios::out|ios::in);
char i[3];
char u[3]="HI";
if (!writeFile)
{
cerr << "error" << endl;
}
writeFile << u <<endl;
writeFile >> i;
cout << i << endl;
}
this is my full code , and result is an empty line.
The fstream object has a position in its output file, and since you opened it just for output and input without any position or writing modifiers, that position is at the end of the file. When you output i to the file, writeFile writes i to the file, and then moves its position past i so when you ask it to write more, you don't overwrite i.
You can reset the position to the start of the file with a call to writeFile.seekg(0), which places that internal position at the 0 position in the file (at the start).
If you're curious about stream manipulation, I'd suggest a look at cppreference.com and specifically its documentation on c++'s input and output libraries here.
Couple things going on here:
You can't open a file for reading if it doesn't exist, this includes a file you want to read and write. No file, no open.
Once you manage to open a file, the stream keeps track of where it is in the file. As you read or write, obviously the location moves.
There is only one location marker in the stream, so you can read to where you want to write, then write. Unfortunately this means any further reading will pick up after the write. If that's not what you want, get and store the current location (with tellg) before writing, and seek (with seekg) to the stored location after writing.
This has some problems such as what if the block of data you wish to insert is longer or shorter than the block of data you want to overwrite? The simple solution to this problem is read into buffer, edit buffer, write buffer back to file.
When you open a file and start writing into it, you overwrite whatever was in the file. If you want to add to a file, open with ios::app. This sets the stream's location to the end of the file. I am unaware of any sort of insert that pushes existing data along as you write in new data.
Some simple file handling example code
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
{
fstream f1("filename", ios::out);
if (f1.is_open())
{
if (f1 << "Hi")
{
cout << "wrote"<<endl;
}
f1.close();
}
fstream f2("filename", ios::out|ios::app);
if (f2.is_open())
{
if (f2 << " there!")
{
cout << "appended"<<endl;
}
f2.close();
}
fstream f3("filename", ios::in);
if (f3.is_open())
{
cout << f3.rdbuf()<< endl;
f3.close();
}
fstream f4("filename", ios::in|ios::out);
if (f4.is_open())
{
f4.seekg(3);
if (f4 << "Fred!")
{
cout << "overwrote"<<endl;
}
f4.close();
}
fstream f5("filename", ios::in);
if (f5.is_open())
{
cout << f5.rdbuf()<< endl;
f5.close();
}
// note the extra ! on the end left over from Hi there! I do not know how
// to get rid of this. I have always just done stuff like this to get around it.
fstream f6("filename", ios::in);
stringstream s1;
string token;
f6 >> token;
s1 << token << " Tim!";
f6.close();
fstream f7("filename", ios::out);
f7 << s1.rdbuf();
f7.close();
// and then moved temp over filename.
fstream f8("filename", ios::in);
cout << f8.rdbuf()<< endl;
f8.close();
}