I would like to open a file for writing, such that the file is wiped and written over at the first write instruction. That is, the file should retain its contents when opened, and only at the first insertion is actually written over.
Using std::fstream, if I use the mode std::ios_base::out, the file is immediately wiped as soon as the constructor is called
#include <fstream>
int main()
{
std::fstream f("test.txt", std::ios_base::out);
// Now test.txt is empty
f << "hello";
}
This behavior would be ok if test.txt does not exists. But if test.txt exists, I would like to have its contents preserved until I write to it. If I open it with
std::fstream f("test.txt", std::ios_base::out | std::ios_base::in);
indeed an existing file is still preserved, and it is written over only on f << "hello".
However, if the file exists and contains more data then the string "hello", then f << "hello" will only overwrite the first 5 characters. I would like the file to be wiped, as if it were opened with std::ios_base::out, but only when I execute f << "hello".
Context
The problem arises with a routine like this:
void do_something(std::ostream& s)
{
//... very long computation
s << "some infos" << std::endl;
}
I call do_something passing to it a stream, which could or could not be a file. If it is a file, I would like to be able to inspect test.txt before the computation is done.
One possibility could be to wrap a fstream in a new object that actually opens the file only when operator<< is called, something like
#include <fstream>
class myfstream {
std::fstream m_f;
std::string m_filename;
public:
myfstream(std::string& filename) : m_filename{filename} { }
template <typename U>
myfstream& operator<<(const U& s) { if (!m_f.is_open()) m_f.open(m_filename, std::ios_base::out); m_f << s; return *this; }
};
The drawback of this solution is the lack of flexibility: if the routine do_something does something else than just calling operator<<, one has to define all the other members of std::ostream, to mimick its behavior. Also, to retain flexibility do_something has to be declared as
template <typename S>
void do_something(S& o);
Is there a better solution? Would it be possible, say, given a fstream to delete all data after the current position of the output indicator?
Update
Apparently, a possible solution is to get the actual write position with tellp() and after closing the file, resize it. See following code:
#include <fstream>
#include <filesystem>
#include <iostream>
int main()
{
typename std::fstream::pos_type size;
{
char d;
std::fstream f("test.txt", std::ios_base::in | std::ios_base::out);
std::cin >> d; // Just to pause
f << "hello";
size = f.tellp();
}
char d;
std::cin >> d; // Just to pause
std::filesystem::resize_file("test.txt", size);
return 0;
}
(The std::cin are there only to pause and be able to check the actual contents of the file).
Testing the program, after the first "pause" the file is still intact. After the second pause, the first characters have been overwritten with the string "hello", but any text following that is still untouched. Finally, resize_file shrinks the file to the actual length of the written string.
The above code does an implicit conversion between a pos_type as returned from tellp() and a std::uintmax_t as required from resize_file.
Is this conversion safe?
Related
I am trying to create class that reading and writing to the same file in c++ using template function and I'm trying to realize the function read() that reading a char or int and returns it and when i tried to run it i got number like -998324343 please help :)
#include<iostream>
#include<fstream>
using namespace std;
template <class T>
class myFile
{
ifstream in;
ofstream out;
public:
myFile(char* fileName)
{
in.open(fileName);
if (!in.is_open())
throw"couldnt open file to reading";
out.open(fileName);
if (!out.is_open())
throw"couldnt open file to writing";
cout << read();
}
T read() {
T x;
in >> x;
return x;
}
};
int main()
{
try {
myFile<int> a("read.txt");
}
catch (char* msg) {
cout << msg << endl;
}
}
Your out and in refer to the same file. So when this happens:
in.open(fileName);
if (!in.is_open())
throw"couldnt open file to reading";
out.open(fileName);
Assuming fileName exists as a file, out will truncate the file, so it becomes empty. The subsequent in >> x; will fail (because the file is empty) and depending on the C++ standard you're compiling against, either x will get zeroed out (since C++11) or remain unmodified (until C++11). I'm assuming you're compiling pre-C++11, in which case what you see is whatever indeterminate value x was initialized with.
Not sure what you need out for, but you either want it to refer to a different file or open it in append mode.
Regardless of whether or not out is truncating the file, the >> operation can fail. If it fails, you will get garbage data (or 0). So you need to check the result of that operation.
Note: Everywhere you are using char* you should be using const char*. The conversion from string literal to char* is deprecated (if you compiled with warnings enabled, you would see this).
suppose I want to write in a .txt file in following format
start-----
-----A----
----------
-B--------
-------end
I've 3 functions that write the parts to file; start to A, A to B then B to end.
My function call are going to be in this order
Func1(starts writing from start of file)
{ }
Func2(needs pointer to position A for writing to file)
{ }
Func3(needs pointer to position B for writing to file)
{ }
Take Fun1 and Func2 for example, Func1 will end writing at A, but the problem is that Func2 needs to go forward from point A. How can I pass a pointer of position A to Func2 so that it'll be able to continue writing from position A in the file?
Since this is c++ we could use file stream object from the standard c++ library.
#include <iostream>
#include <fstream>
using namespace std;
void func1(ofstream& f)
{
f << "data1";
}
void func2(ofstream& f)
{
f << "data2";
}
int main () {
ofstream myfile ("example.txt");
if (myfile.is_open())
{
func1(myfile);
func2(myfile);
myfile.close();
}
else cout << "Unable to open file";
return(0);
}
However this approach is universal. When you are working with file, you get some file identificator. It could be a FILE struct, Win32 HANDLE etc. Passing that object between functions will allow you to continuously write the file.
Not sure how you're outputting to a file (using which output method), but normally, the file pointer keeps track itself where it is up to.
eg using fstream
ofstream outFile;
outFile.open("foo.txt");
if (outFile.good())
{
outFile<<"This is line 1"<<endl
<<"This is line 2"; // Note no endl
outFile << "This is still line 2"<<endl;
}
If you pass the outFile ofstream object to a function, it should maintain position in the output file.
Previously answered: "ofstream" as function argument
I need redirect the copy of std::cout to the file. I.e. I need see the output in console, and in file. If I use this:
// redirecting cout's output
#include <iostream>
#include <fstream>
using namespace std;
int main () {
streambuf *psbuf, *backup;
ofstream filestr;
filestr.open ("c:\\temp\\test.txt");
backup = cout.rdbuf(); // back up cout's streambuf
psbuf = filestr.rdbuf(); // get file's streambuf
cout.rdbuf(psbuf); // assign streambuf to cout
cout << "This is written to the file";
cout.rdbuf(backup); // restore cout's original streambuf
filestr.close();
return 0;
}
then I write string to the file, but I see the nothing in console. How can I do it?
The simplest you can do is create an output stream class that does this:
#include <iostream>
#include <fstream>
class my_ostream
{
public:
my_ostream() : my_fstream("some_file.txt") {}; // check if opening file succeeded!!
// for regular output of variables and stuff
template<typename T> my_ostream& operator<<(const T& something)
{
std::cout << something;
my_fstream << something;
return *this;
}
// for manipulators like std::endl
typedef std::ostream& (*stream_function)(std::ostream&);
my_ostream& operator<<(stream_function func)
{
func(std::cout);
func(my_fstream);
return *this;
}
private:
std::ofstream my_fstream;
};
See this ideone link for this code in action: http://ideone.com/T5Cy1M
I can't currently check if the file output is done correctly though it shouldn't be a problem.
You could also use boost::iostreams::tee_device. See C++ "hello world" Boost tee example program for an example.
Your code does not work, because it is the streambuf that determines where the output written to a stream end up, not the stream itself.
C++ does not have any streams or streambufs that support directing the output to multiple destinations, but you could write one yourself.
I am working on a C++ code and I wish to do the following:
In the code there is a new type, T, there is a method defined on T that prints some information to a type FILE* variable.
I would like to do some work on this string inside of the program, so I would like to have a variable of type string (or even char*) that will contain what is printed to the screen (if I give the printing function stdout as the File*).
How can I do this ? maybe I can create some FILE* variable and then create (somehow) a string/char* variable with the information that is stored in that File* variable we created ?
Any help is appreciated!
POSIX 1.2008 fmemopen, open_memstream functions create a FILE* pointer which writes to (and/or reads from) memory.
If it does not work for your platform (and there is no other way to hook into FILE *), then you're out of luck.
The next thing I'd try is creating an anonymous pipe, (POSIX pipe, Windows CreatePipe), wrapping its writing side into FILE * (POSIX fdopen, plus Windows _open_osfhandle to get a CRT fd from HANDLE). Here you have to ensure that the pipe's buffer size is enough, or to spawn a thread for reading the pipe. Don't forget to fflush the writing side after the method is done (or use setbuf to disable buffering).
There are several platform-independent ways to do it.
In C++ you can use stringstream(http://www.cplusplus.com/reference/sstream/stringstream/), which has many << operator overloads. So if you pass a reference to ostream& (not oFstream) to the output method, you can easily switch between files, stadard output stream and string outputs, because all this streams are inherited from ostream. Then you can get std::string object from stringstream and get C-string from it if you need.
Code example:
Output function (or method, then you don't need the second argument from the example):
void PrintMyObjectToSomeStream(std::ostream& stream, const MyClass& obj)
{
stream << obj.pubField1;
stream << obj.pubField2;
stream << obj.GetPrivField1();
stream << "string literal";
stream << obj.GetPrivField2();
}
Usage:
MyClass obj1;
std::ofsstream ofs;
std::stringstream sstr;
//...open file for ofs, check if it is opened and so on...
//...use obj1, fill it's member fields with actual information...
PrintMyObjectToSomeStream(obj1,std::cout);//print to console
PrintMyObjectToSomeStream(obj1,sstr);//print to stringstream
PrintMyObjectToSomeStream(obj1,ofs);//print to file
std::string str1=sstr.str();//get std::string from stringstream
char* sptr1=sstr.str().c_str();//get pointer to C-string from stringstream
Or you can overload operator<<:
std::ostream& operator<<(std::ostream& stream, const MyClass& obj)
{
stream << obj1.pubField;
//...and so on
return stream;
}
then you can use it in this way:
MyClass obj2;
int foo=100500;
std::stringstream sstr2;
std::ofstream ofs;//don't forget to open it
//print to stringstream
sstr2 << obj2 << foo << "string lineral followed by int\n";
//here you can get std::string or char* as like as in previous example
//print to file in the same way
ofs << obj2 << foo << "string lineral followed by int\n";
Using FILE is more C than C++ but you can think how to switch between fpirntf and sprintf or use Anton's answer.
Is there any way to keep a stream (to read or write in a file) open from a function to another in C++?
Yes, you can either create the stream outside of the functions and pass it as a parameter to the methods:
void myFunction(ifstream &stream) {...}
Later close the stream when you are done with it: stream.close().
Or create the stream within the first function and return it to the calling method and then pass it to the second function.
Pass it by reference
void myFunction(ifstream &myStream)
Make it global or pass it as an argument but ensure that if you pass it as an argument you past it by reference not by value! If you pass it by value the compiler will NOT complain and weird things start happening.
Since C++11 file stream got move constructor (6). You can use it to pass opened stream between functions. Consider the following code snippet:
#include <iostream>
#include <fstream>
bool open_stream(const std::wstring& filepath, std::ifstream& stream)
{
std::ifstream innerStream;
innerStream.open(filepath.c_str(), std::ios::in | std::ios::binary);
if (innerStream.is_open())
{
stream = std::move(innerStream); // <-- Opened stream state moved to 'stream' variable
return true;
}
return false;
} // <-- innerStream is destructed, but opened stream state is preserved as it was moved to 'stream' variable
Consider the next code to illustrate the usage of open_stream:
int main()
{
std::ifstream outerStream;
std::wcout << L"outerStream is opened: " << outerStream.is_open() << std::endl; // <-- outerStream is opened: 0
if (!open_stream(L"c:\\temp\\test_file.txt", outerStream))
{
return 1;
}
std::wcout << L"outerStream is opened: " << outerStream.is_open() << std::endl; // <-- outerStream is opened: 1
// outerStream is opened and ready for reading here
return 0;
}