Can't write/read with fstream - c++

When i write like this
std::fstream file ("data.dat", std::ios::in | std::ios::out);
if (!file)
{
std::cerr << "Error";
exit(1);
}
I receive "Error". When i rewrite the whole thing like this
std::fstream file;
file.open("data.dat", std::ios::out | std::ios::in);
if (!file)
{
std::cerr << "Error";
exit(1);
}
data.dat is being created, and i manage to write and read. Am doing this on VS 2013, in addition to that i tried compiling on 6.0 version and both ways have worked. I have no clue what the problem is.

You get the error because you instructed fstream to open the file for reading as well. If the file does not exist flags in | out will give you an error. Try it with only out and it should work. If you want to do write and read on a file that does not exist you need an extra flag, either append (app) or truncate (trunc)

Related

Opening a file to read and write, create it if it doesn't exist

I was trying to create a file in both read and write modes, but it doesn't create the file, what can be the problem?
This is code:
fstream file("NameFile.txt", ios::out| ios::in);
The program will start, but it will not create any files.
When you open the file using fstream:
To read, the file is required to exist;
To write you need to specify a write mode, ofstream would do that for you, but with fstream you need to do it yourself:
Replaces the contents of the file when you write (ofstream default mode).
std::fstream file("NameFile.txt", std::ios::out | std::ios::in | std::ios::trunc);
^^^^^^^^^^^^^^^
Appends to the existing data in the file when you write.
std::fstream file("NameFile.txt", std::ios::out | std::ios::in | std::ios::app);
^^^^^^^^^^^^^
Note that after reading or writing you'll need to set the offset position in the file, for instance:
std::string s = "my string";
std::string in;
file << s;
file >> in;
file >> in will not read anything, the position indicator is at the end of the file after file << s, you'll need to reset it if you want to read previously written data, for example:
file << s;
file.seekg(0);
file >> in;
This resets the read position indicator to the beggining of the file, before the file is read from, more about it here:
https://en.cppreference.com/w/cpp/io/basic_fstream
well, you initialized an object, now to create a file use
file.open();
see
fstream won't create a file

How can I open a file in c++, without erasing its contents and not append it?

I am trying to find a way using which I can Edit the contents in a binary file, without reading the whole file.
Suppose this is my file
abdde
And I want to make it
abcde
I tried following:-
Attempt 1)
ofstream f("binfile", ios::binary);
if(f.is_open()){
char d[]={'c'};
f.seekp(2,ios::beg);
f.write(d, 1);
f.close();
}
//the file get erased
Output:
**c
Attempt 2)
ofstream f("binfile", ios::binary | ios::app);
if(f.is_open()){
char d[]={'c'};
f.seekp(2,ios::beg);
f.write(d, 1);
f.close();
}
//the file simple gets append seekp() does nothing
Output:
abddec
Attempt 3)
ofstream f("binfile", ios::binary | ios::app);
if(f.is_open()){
char d[]={'c'};
f.seekp(2);
f.write(d, 1);
f.close();
}
//same as before the file simple gets append seekp() does nothing
Output:
abddec
And if I just try to replace the 1st byte of the file, which is 'a' with 'h'
ofstream f("binfile", ios::binary);
if(f.is_open()){
char d[]={'c'};
f.seekp(ios::beg);
f.write(d, 1);
f.close();
}
//file is erased
Output:
h
What do I do? Is it even possible for the OS to allow a program to edit a file at any point own its own?
std::ios::app means the cursor is put at the end of the file before every write. Seeking has no effect.
Meanwhile, std::ios::binary goes into "truncation" mode by default for an output stream.
You want neither of those.
I suggest std::ios::out | std::ios::in, perhaps by just creating a std::fstream fs(path, std::ios::binary) rather than using an std::ofstream.
Yes, it's a bit confusing.
(Reference)

fstream is not writing anything on the file

I'm trying to write some things to a text file but it won't even create the file. I will appreciate a lot if you can help me with this. Thanks.
#include <fstream>
#include <iostream>
int main(){
std::ofstream file;
file.open("path/to/file");
//write something to file
file << "test";
//printing to screen
std::cout << file.rdbuf();
//closing file
file.close();
return 0;
}
The following line is your culprit:
std::cout << file.rdbuf();
You cannot use rdbuf to output a file that was opened for write operations only.
Remove that line and your file will be written correctly.
If you want to read your file after you've finished writing to it:
Solution 1:
Open file for both read and write operations using fstream:
std::fstream file("path/to/file", std::ios::in | std::ios::out);
// ... write to file
file.seekg(0); // set read position to beginning of file
std::cout << file.rdbuf();
Solution 2:
Create a new std::ifstream to read from file:
// ... write to file
file.close(); // call `close` to make sure all input is written to file
std::ifstream inputFile("path/to/file");
std::cout << inputFile.rdbuf();
salesFile.open("C:\\Users\\Tebsan\\Desktop\\Coding\\c++\\re\\salesFile.txt"); // ...try to open existing file
if( !salesFile.is_open() ) // ...else, create new file...
salesFile.open("C:\\Users\\Tebsan\\Desktop\\Coding\\c++\\re\\salesFile.txt", ios_base::in | ios_base::out | ios_base::trunc);
You have to call fstream::open with an explicit openmode argument of
ios_base::in | ios_base::out | ios_base::trunc
Otherwise open will fail due to ENOENT.
Thanks for the help!!!
I Learned new things from this. The funny thing is that the issue was the name of the file, apparently the name was too long, and for the new file that included file stream I just added stream at the end of the name, so the compiler kept running the first file (without file stream)...

fstream in and out on nonexistent file

Is it possible to open an fstream on a file that does not exist with both ios::in & ios::out without getting an error?
To open an fstream on a file that does not exist for input and output (random access) without getting an error, you should provide the flags fstream::in | fstream::out | fstream::trunc in the open (or constructor) call. Since the file does not already exist, truncating the file at zero bytes is no drama.
You may want an error when opening a file that doesn't exist when specifying only ios::in since you'll never be able to read from the stream so failing early in this case will prevent surprise failures later on.
The answer to your question unfortunately is: "No", this is not possible in a single C++ statement.
Yes, many people will answer, that you can use the combined flags fstream::in | fstream::out | fstream::trunc. But that answer is nonsense. fstream::trunc means, that the output file will be truncated to size zero upon opening. But then, why would you like to open an empty file for reading and writing? Except for the rare case, that you need a file as a temporary store for some of your application's data, that you will first write and later read back, there is no use for this flag combination.
Some people recommend to first try to open with fstream::in | fstream::out (and possible further flags like fstream:app or fstream::binary as needed) and then check the file's error status: If the file could not be opened, then re-try the open operation including | fstream::trunc. This solution has several caveats, however. For example, if your file system is mounted via NFS, the first attempt to open the file in read/write-mode might fail due to temporary network issues. If the second attempt (the one including the fstream::trunc flag) then succeeds, there goes your wounderful data, that you have collected so far.
The safe solution is to first open the file for appending only (which will create the file, if it doesn't exist, but will not truncate it) and then close it immediately and open it a second time in read-write mode. This can be achieved with the following code: Note, that an ofstream is first constructed and then immediately discarded.
std::string filename { "test.txt" };
(void) std::ofstream(filename, std::ostream::app);
std::fstream file(filename);
Alternatively, if you need further flags, like binary, use:
std::string filename { "test.txt" };
(void) std::ofstream(filename, std::ofstream::app | std::fstream::binary);
std::fstream file(filename, std::fstream::in | std::fstream::out | std::fstream::binary);
I hope, that in C++25 (or whichever standard is next), they finally add a flag std::fstream::create to create non-existant output files, if read-write-mode is requested.
#include <fstream>
ofstream out("test", ios::out);
if(!out)
{
cout << "Error opening file.\n";
return 1;
}
ifstream in("test", ios::in);
if(!in)
{
cout << "Error opening file.\n";
return 1;
}
If an error occurs the message is displayed and one (1) is returned. However it is possible to compile and execute just ofstream out("test", ios::out); and ifstream in("test", ios::in); without any errors. Either way the file test is created.
#include <iostream>
#include <fstream>
using namespace std;
int main () {
fstream f("test.txt", fstream::in | fstream::out);
cout << f.fail() << endl;
f << "hello" << endl;
f.close();
return 0;
}
This code will print 1 and will not create "test.txt" file, if it does not exit. So it is not possible to open and fstream on a file that does not exist without getting an error.
std::fstream f("test.txt", std::ios_base::out);
f.close(); //file now exists always
f.open("test.txt", fstream::in | std::ios_base::out);
//f is open for read and write without error
I haven't checked to guarantee that it will open without error, but I feel pretty confident that it should.

Is there a function in C++ that creates a .bin file, or is this code missing something?

I have a code that looks like this:
int main () {
fstream file;
file.open("test.bin", ios::out | ios::binary);
if(!file.is_open())
{
return -1;
}
int n = 3;
file.write(reinterpret_cast<char*>(&n), sizeof(n));
file.close();
return 0;
}
when I run it alone, it exits with -1, so obviously it failed to open "test.bin". However, if I save a blank notepad file as "test.bin", and run it, it works fine. What I am wondering is how I can get my C++ program to automatically generate an empty file "test.bin" if a file called "test.bin" does not already exist.
Your code snippet is wrong since it's trying to write to a file that you've opened for input. If you want to write to the file, simply use ios::out instead of ios::in.
If you want to open the file for reading but create it if it does not exist, you can use:
file.open("test.bin", ios::in | ios::binary);
if(!file.is_open()) {
file.open("test.bin", ios::out | ios::binary);
int n = 3;
file.write(reinterpret_cast<char*>(&n), sizeof(n));
file.close();
file.open("test.bin", ios::in | ios::binary);
if(!file.is_open()) {
return -1;
}
}
This will initialize the file with the integer 3 as the default contents, if it doesn't already exist.
If it does exist, it will leave the contents alone. In either case, you'll have the file open at the first byte.
I'd assume you could probably just do it by opening and closing a file:
if (GetFileAttributes("test.bin") == INVALID_FILE_ATTRIBUTES)
{
fstream file;
file.open("test.bin", ios::out);
file.close();
}
One option is to open for read/write and seek to the beginning of the file.
Then, you may read, write, or do whatever you wish.