how do i legitimately change filename value of ofstream object? - c++

I'm having troubles with ofstream , which is - when I change value of ofstream object like this
ofstream o_save;
/*code*/
o_save = ofstream(filename); //Problem is here
...the line above completely erase contents of file.
The question is how do I legitimately change filename value of ofstream object ?
P.S. I cant define it when I declare it, because I want it global and I'm not sure which save file I select.

The question is quite vague and contradictory, and the OP seems to have slept after asking the question. So I shall try to peek inside his head and try to elaborate what he wants.
For opening a file, there are many modes for that. Open it like this.
ofstream o_value ;
o_value.open("file.txt") ;
If you want to preserve the original contents of that file, use..
o_value.open("file.txt", ios::app) ;
If you want to close it later and open another one, close using...
o_value.close() ;
Chaning of file names is normally not allowed in case of ofstream. You can use rename from <cstdlib>. You can delete a file though using remove("file.txt") in <cstdio> .

What does it mean to "change the name" of an ofstream object?
The only "name" an ofstream object has is the name of the
variable. An ofstream object is a data stream. You can (on
some systems) change the name of the file it is associated with,
using rename, but somehow, I don't think this is what you want
either. You can also close the stream, and reopen it on another
file.
You cannot assign between iostream objects. If worse comes to
worse, you can declare the global object as a pointer, and
assign to it (using *o_save to write to it).
Finally, the standard says that when you open an ofstream, you
truncate the file, if one exists. If this is not what you want
to do, then you have to add some flags to the open mode. If you
add std::ios_base::app, for example, you will no longer
truncate the file, and all writes will be to the end of file
(atomically, if the system supports it). Alternatively (albeit
quite surprising), you could add std::ios::in to the flags;
this will fail if the file doesn't exist, but will allow writing
anywhere in the file. This is the only way to open a file for
writing if you want to be able to write anywhere in the file,
even if you don't want to read it.

The ofstream does not have some kind of an abstract name attribute, the name is just a parameter to some of its member functions, in that sense asking how to
change filename value of ofstream object
is meaningless.
In general you can rename files with std::rename from <cstdlib> or use Boost.Filesystem.

Related

How to get raw bytes written to ostream by an external library without creating a file

(My previous questions was closed as a duplicate of Are there binary memory streams in C++ which is ridiculous, since i can't change the implementation of the library I'm using)
I'm using a library (Poco) to create zip files. It takes ostream as an input and writes the data of the zip file into it. Something like:
std::ofstream ofs("file.zip", std::ios::binary);
Compress compress(ofs);
// add data to compress ...
compress.close();
// now file.zip contains added file
This works. But I want to be able to create a zip in memory without creating a file. I tried using stringstream instead of ofstream, i get additionl newline characters in the data in the zip file is corrupted. Is there any other stream i can use?
(If someone still thinks it's a duplicate, I'm gonna need an explanation, since I don't see how this other question is helpful for me)
Use a std::stringstream -- that will create an in-memory string that you can write to as an ostream, and WILL NOT add extra newlines. If you later copy the string to an fstream that was opened in text mode (such as std::cout), then that process may add extra CR characters that are not in the string (nor in the original output).
If you are seeing extra characters corrupting your stream, they are coming from somewhere else -- something besides you compress call/lib is writing to the stream, or something with how you are looking at your stream is doing something.
If you're on linux, how about creating an anonymous file using memfd_create? You can then open /proc/self/fd/<fd> and do your stuff. Some implementations of std::ofstream may even provide a constructor that takes a FILE*, you can check if that's the case on your system.

preferred c++ i/o stream method: fstream or ifstream/ofstream or something else entirely?

I have created a roster program that accepts user input to create/write/delete information into and out of a specified text file. My issue now becomes wanting to create a lasting text file that isn't overwritten every time I re-run the program and am not sure if using fstream or a combination of of/ifstream is better practice, or if there is maybe a third option I missed when checking the reference docs.
Right now I am simply using: std::ofstream outfile("roster.txt"); which works, until I kill and re-run the program to which my text file is now wiped clean.
check out the append flag. it writes to the end of an existing file.
http://www.cplusplus.com/doc/tutorial/files/
example here.
std::ofstream outfile("roster.txt" , ios::app)

Write to the start of a textfile in c++

I was looking for an easy way to write something into the first line of an already existing textfile. I tried using ofstream like this:
ofstream textFileWriter("Data/...txt");
if (textFileWriter.is_open())
{
textFileWriter << "HEADER: stuffstuff";
}
But it would delete everything which used to be in that file, even though the ofstream wasn't constructed with std::ofstream::trunc. I cannot use std::ofstream::app, since it is important to write into the first line.
Copying the whole textfile into a vector which has the line already and then writing it back would be my last option, but something I would really like to avoid, since the textfiles are quite large.
You can't simply "append" to the beginning of a file.
The common solution is to open a new (temporary) file, write your new header, write the rest of the original file to the temporary file, and then "rename" (using the OS system calls) the temporary file as the original file.
Or as you say in your question, read the original file into an in-memory buffer (e.g. a vector) and do the modification in that buffer, and then write the buffer to the file.

Writing at the beginning of a file, keeping file contents

I have a text file where I want to write. I want to keep the file content always. I want to write following a "FIFO" (last write always on the top line of the file).
I try using fout.open("filename"); with ate mode to keep file content, after that use seekg(0) trying to take back writing cursor to the begining of the file. Didn't work.
The unique way I found to do that I think it's so time-expensive, copy all the file content to a temporary file. Write want I want to write and after that write the content of the temp file at the end of the target file.
There must be an easy way do this operation?
Jorge, no matter what you will have to rewrite the entire file in memory. You cannot simply keep the file where it is and prepend memory, especially since it's a simple text file (maybe if there was some form of metadata you could...)
Anyways, your best chance is to flush the old contents into a temporary location, write what you need and append the old contents.
I'm not sure what you're asking for. If you want to add a
line to the beginning of the file, the only way is to open a
new, temporary file, write the line, copy the old file into
after the new line, then delete the old file and rename the
temporary.
If the original line has a fixed length, and you want to replace
it, then all you have to do is open the file with both
ios_base::in and ios_base::out.
First, you should realize that files are historically streams, i.e. they can only be read and written in one direction. This comes from the times when files were stored on tapes, which could move in one direction (at that time).
However, if you only want to prepend, then you can just store your file backwards. Sounds silly? Maybe, but this would work with just a little overhead.
Apart from that, with current OS's you will need to make a copy to prepend. While files are not streams anymore, and can be accessed randomly on a harddisk, they are still made to grow in one direction. Of course you could make a filesystem, where files grow in both directions, but I have not heard of one.
With <fstream> you may use the filebuf class.
filebuf myfile;
myfile.open ("test.txt", ios::in | ios::out);
if (!myfile.is_open()) cout << "cannot open" << endl;
myfile.sputn("AAAA", 4);
myfile.close();
filebuf myfile2;
myfile2.open ("test.txt", ios::in | ios::out);
if (!myfile2.is_open()) cout << "cannot open 2" << endl;
myfile2.sputn("BB", 2);
myfile2.close();
write to a string in order you want, then flush to the file

c++ overwrite already opened file

I am opening a file with ifstream to check if it exists. Then I close it and open it with ofstream to write to it, and I think setting ios::trunc flag allows me to overwrite it.
However I'd like the ability to keep the file open if it exists, but I used an ifstream to open it so does that mean I can't write to the file till I close and re-open using fstream or ofstream? I didn't use fstream to begin with because that wouldn't tell me if the file was already there or not.
Just open a read-write fstream on the file. You can test if the file previously existed (and was non-empty) by seeking to the end and seeing if you're at a non-zero offset. If so, the file existed, and you can do whatever with it. If not, the file didn't exist or was empty. Assuming you don't need to distinguish between those two cases, you can then proceed as if it did not exist.
For example:
// Error checking omitted for expository purposes
std::fstream f("file.txt", std::ios::in | std::ios::out);
f.seekg(0, std::ios::end)
bool didFileExist = (f.tellg() > 0);
f.seekg(0, std::ios::beg);
// Now use the file in read-write mode. If didFileExist is true, then the
// file previously existed (and has not yet been modified)
The setting ios::trunc erases previous contents of the file.
Try opening the file without this setting; with only the 'write' setting.
this is touching very serios problem - race conditions - what if somebody manages to do something with this file between closing and reopening? unfortunately iostream does not provide any means of resolving that issue - you can use cstdio FILE. If you want to turncate file if exists or create new one if not use fopen(name, "w"). If you want to turncate file if it exists or fail otherwise, then it seems standard library has nothing to offer, and you should go to other libraries or platform specific functions like OpenFile in windows.h