This question already has answers here:
How to truncate a file while it is open with fstream
(3 answers)
Closed 6 years ago.
Although I found a lot of stuff about std::fstream on SO, I still can't understand how it operates. Let's see this minimal example:
#include <fstream>
#include <string>
int main()
{
std::fstream fs{ "somefile.txt", std::fstream::out | std::fstream::in };
std::string line;
while (std::getline(fs, line))
{
// reads the whole file
}
// the purpose is to overwrite the whole file
fs.seekp(0, std::ios_base::beg); // moves at the beginning
fs << "Hello world!" << std::endl; // writes in the file
// possibly other read/write
}
This does not work, it seems that one cannot firstly read, and then write in the same stream according to everything I read about. I know the workaround that consists in closing the file, then opening it with the std::ios_base::trunc flag. However, that seems to be nonsensical: why is there such a limitation? Cannot we technically just overwrite the file after the reading?
The loop iterates until the fail bit gets set. Just clear() the flags prior to the seek:
fs.clear();
If you only want to overwrite the starting bit that is sufficient. If also want to truncate the stream I'd explicitly close() and open() it, where the open() would not set std::ios_base::in.
After reading the whole file, the fs is now in eof state. You need to clear the state so it can do following IO operations.
Related
I have the these code:
FILE *fp;
_wfopen_s(&fp, m_file, L"rb")
and
FILE *wmp
_wfopen_s(&wmp, s_file, L"wb")
I want to know how can I change above code to ofstream or ifstream, I know I can do something like this "outfile.open("junk.dat", ios::binary | ios::out);" with ofstream, But how I can put "s_file" and "&wmp" in ofstream?
First of all, if you want to continue using wide characters you should be using std::wofstream and std::wifstream.
Secondly, you don't use a FILE* at all, so no &wmp anywhere. The object you define is the file which you use to read from or write to. So you can have something like
std::wofstream wmp(s_file, wios::out | wios::binary);
if (wmp)
{
// Here you have an open output stream, write wide characters to it
wmp << L"Hello world\n"; // Writes a string to the file
// Write some binary data to the file
wmp.write(reinterpret_cast<wchar_t*>(some_data),
size_of_some_data_in_bytes / sizeof(wchar_t));
// The division is needed, as `write` write in units of `wchar_t`, not bytes
// This is problematic if some of the data you want to write isn't an even
// multiple of `sizeof(wchar_t)`
// And so on...
// Finally when done, close the file
wmp.close();
}
Note that if you are not writing strings to the file, but only raw binary data then I suggest you use plain std::ofstream instead, as you won't have to think in units of wchar_t and can just think in units of "bytes".
If you want to learn more this is an excellent reference about the C++ I/O classes.
This question already has answers here:
Read a file backwards?
(7 answers)
Closed 8 years ago.
How can I read a text file in reverse order (i.e. from eof) using C++?
Yes, but you basically have to do it manually.
The basic algorithm is as follows:
Seek to the end of the file with is.seekg(0, is.end)
Determine the file size with is.tellg()
Repeatedly seek backwards and read chunks of the file until you reach the front
If the file is small enough so the entire contents easily fit within memory, it will be both far faster and far easier to code to read the file forward into a string and then reversing that string after the fact.
If the contents won't fit in memory, you'll have to use nneonneo's solution. It would probably be best to turn off buffering.
Just use the seekg and related functions in istream class. Here is a working example. Tested.
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ifstream in("file.txt");
// Get the length of the file
in.seekg(0, in.end);
int len = in.tellg();
// Start reading the file in reverse
char c;
while (len--)
{
in.seekg(len, in.beg);
in >> c;
cout << c;
}
}
(1) default constructor
Constructs an ofstream object that is not associated with any file.
Internally, its ostream base constructor is passed a pointer to a newly constructed filebuf object (the internal file stream buffer).
what happened to << when using ofstream without any filename pointed?
ofstream ofstream;
ofstream<<1<<endl;
where is the "1" go? is there any problems? I tried it, no issues. but I can't found any code clue for this, can anybody show the internal code explain for it?
Nothing happens.
[C++11: 27.9.1.1/3]: In particular:
If the file is not open for reading the input sequence cannot be read.
If the file is not open for writing the output sequence cannot be written.
A joint file position is maintained for both the input sequence and the output sequence
The stream is closed, an error flag is set and the data is ignored.
Example:
#include <iostream>
#include <fstream>
int main()
{
std::ofstream ofs;
ofs << 1 << std::endl;
std::cout << ofs.good() << std::endl;
}
// Output: 0
Live demo
The short version: the operations on the ofstream all fail, causing nothing to happen. The data that you write is lost and not stored anywhere, and the failbit will be set, causing the stream's fail() member function to return true.
The long version: when an ofstream is constructed without specifying a file, it default-constructs a filebuf. This creates a filebuf where is_open evaluates to false. As part of the stream insertion operation, the data to be written will need to be sent to the disk by calling filebuf::overflow, which, since is_open is false, will return EOF, causing the operation to fail.
Hope this helps!
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to use istream with strings
std::ifstream ifile(absolute_file_path.c_str(),std::ios::binary | std::ios::in | std::ios::ate);
if (ifile.is_open()==false)
{
throw std::runtime_error("Unable open the file.");
}
std::stirng file_content;
//here I need good way to read full file to file_content
//note: the file is binary
ifile.close();
This are ways I know:
1.Maybe not safe
file_content.resize(ifile.tellg());
ifile.seekg(0,std::ios::beg);
if(!ifile.read(const_cast<char *>(file_content.data()), file_content.size()));
{
throw std::runtime_errro("failed to read file:");
}
ifile.close();
2.Slow
file_content.reserve(ifile.tellg());
ifile.seekg(0,std::ios::beg);
while(ifile)
{
file_content += (char)(ifile.get());
}
If the file is binary, it might contain '\0' which is a weird character to be contained in an std::string. Although I think you could do that, you will be asking for problems because some operations on a std::string take a const char* which is null-terminated. Instead, go with std::vector<char>, a much safer way.
If you go with strings anyway, just do a loop calling std::string::append(size_t, char).
while(!ifile.eof()) {
contents.append(1, ifile.get());
}
EDIT: I think you can also do something in the lines of:
std::string contents(std::istreambuf_iterator<char>(ifile), std::istreambuf_iterator<char>());
You should be clear with binary file and string. Do you mean to read the content of that file, or you want to read binary representation of the file to string? Normally an unsigned char[] buffer is used to store content of binary files. And string is used to store content of a text file.
Any idea why the following would fail?
std::fstream i(L"C:/testlog.txt", std::ios::binary | std::ios::in);
int test = 0;
i >> test;
fail() is returning true. The file exists and is opened.
I checked
i._Filebuffer._Myfile._ptr
and it is pointer to a buffer of the file so I don't see why it is failing.
You're opening the file in binary mode. The extraction operators were meant to be used with text files. Simply leave out the std::ios::binary flag to open the file in text mode.
If you actually do have a binary file, use the read() function instead.
Edit: I tested it too, and indeed it seems to work. I got this from CPlusPlus.com, where it says:
In binary files, to input and output data with the extraction and insertion operators (<< and >>) and functions like getline is not efficient, since we do not need to format any data, and data may not use the separation codes used by text files to separate elements (like space, newline, etc...).
Together with the description of ios::binary, which simply states "Consider stream as binary rather than text.", I'm utterly confused now. This answer is turning into a question of its own...
The following:
#include <fstream>
#include <iostream>
using namespace std
int main() {
std::fstream i("int.dat" , std::ios::binary | std::ios::in);
int test = 0;
if ( i >> test ) {
cout << "ok" << endl;
}
}
prints "ok" when given a file containing the characters "123". Please post a similar short test that illustrates your code failing.