1

I need to write two programs write.cpp & read.cpp to run simultaneously. One of them write(overwrite) to a file and the other one reads from it.

Basically, there is always only one line in the file.

write.cpp performs the operation successfully but read.cpp doesn't show anything. Using tail -f also shows incorrect result.

write.cpp:

#include <stdio.h> #include <ctime> #include <unistd.h> #include <iostream> #include <fstream> #include <string> using namespace std; int main () { ofstream myfile; int i = 70; char c; while(i <85) { myfile.open ("example.txt"); c = i++; myfile << c << endl; myfile.close(); sleep(1); } return 0; } 

read.cpp:

#include <iostream> #include <fstream> #include <string> #include <unistd.h> using namespace std; int main () { string line; ifstream myfile ("example.txt"); if (myfile.is_open()) { while ( myfile.good() ) { sleep(1); getline (myfile,line); cout << line << endl; } myfile.close(); } else cout << "Unable to open file"; return 0; } 

May I know which part of both programs causes the problem and how may I solve it?

8
  • read.cpp doesnt show anything. Does it exit? Does it get as far as myfile.good(). Does it get past it? Commented Feb 20, 2013 at 10:30
  • @StoryTeller Good idea, but it isn't portable. Commented Feb 20, 2013 at 10:31
  • @PeterWood yes it exits Commented Feb 20, 2013 at 10:31
  • @PeterWood That's a good point. If the reader starts before the writer has passed at least once through the loop, the open in it may fail. Commented Feb 20, 2013 at 10:31
  • 1
    @PeterWood, the inclusion of unistd.h doesn't imply portability in mind. Commented Feb 20, 2013 at 10:50

2 Answers 2

3

You're doing the right thing in the writer, but once you've read to end of file, the input stream becomes unusable until the fail condition is set. The best solution is probably to do exactly what you're doing in the writer: open and close the file each time in the read loop.

Be aware that there will be a moment when the file is empty; when you open the file for writing in the writer, it will be truncated, and if the reader happens to try to read at precisely this moment, it will find an empty file. (It's no big problem; just be aware of it, maybe skipping the sleep if you find an empty line.)

Sign up to request clarification or add additional context in comments.

12 Comments

your suggestion worked, thanks. I just wished there was a way we could avoid closing the file in the read.cpp's loop.
I got feeling may be you are trying to solve reader/writers problem? If so please do share as their are efficient solution to this problem...
@rahman Why? If you were trying the read every couple of milliseconds, I could see the motive, but once per second. FWIW: however: both when writing and reading, you can seek to the beginning of the file before each operation (pseek and gseek). In the case of reading, you'll also have to clear the end of file condition (clear). Independently of performance, considerations, this might be preferable for writing, because it means that the reader will never see an empty file. It does mean that you'll have to always write the same number of characters, however.
@JamesKanze Actually yes, writing is going to be every 100 milliseconds, and reading would be about the same. Still if you think 100 milliseconds is ok, please let me know. about pseek and gseek, I will check them out, but do you mean if I use them, I won't have to open&close files repeatedly? what is 'clear'? do you mean I use a '\n' or so? thanks
@PeterWood Yes, and seekg instead of gseek. Typing too fast.
|
2

To add some detail to my answer to your previous question, here is how you could use Boost's interprocess communication to achieve this if you insist on using a file for .

A writer may look like this:

#include <boost/interprocess/sync/file_lock.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <fstream> #include <iostream> int main() { using namespace boost::interprocess; std::string line, shared_filename = "shared"; { std::ofstream create_shared_file(shared_filename.c_str()); } for (;;) { std::cout << "Enter some text: "; std::cin >> line; try { file_lock lock(shared_filename.c_str()); scoped_lock<file_lock> lock_the_file(lock); std::ofstream shared_file(shared_filename.c_str(), std::ofstream::trunc); shared_file << line << std::endl; shared_file.flush(); } catch (interprocess_exception const& e) { std::cerr << e.what() << std::endl; } } } 

The corresponding reader:

#include <boost/interprocess/sync/file_lock.hpp> #include <boost/interprocess/sync/sharable_lock.hpp> #include <fstream> #include <iostream> #include <unistd.h> int main() { using namespace boost::interprocess; std::string line, shared_filename = "shared"; for (;;) { try { file_lock lock(shared_filename.c_str()); std::cout << "Waiting for file lock..." << std::endl; sharable_lock<file_lock> lock_the_file(lock); std::cout << "Acquired file lock..." << std::endl; std::ifstream shared_file(shared_filename.c_str()); shared_file >> line; if (line.empty()) { std::cout << "Empty file" << line << std::endl; } else { std::cout << "Read: " << line << std::endl; } } catch (interprocess_exception const& e) { std::cerr << "Could not lock " << shared_filename << ": " << e.what() << std::endl; } std::cout << "Sleeping..." << std::endl; sleep(2); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.