get wrong file size with c++ ios::ate - c++

I am trying to get the file size of a file with c++. The code is like this:
ifstream fin(filepth, ios::in | ios::binary | ios::ate);
if (!fin.is_open()) {
cout << "cannot open file:" << filepth << endl;
}
int len = fin.tellg();
fin.seekg(0, ios::beg);
fin.clear();
cout << "file length is: " << len << endl;
cout << "file length is: " << fs::file_size(fs::path(filepth)) << endl;
It turns out that the method of ios::ate got the wrong result. What did I miss and how could I got the correct result ?

I got the reason of the problem. My file is about 9 gigabytes long, which cannot be expressed by a 32 bit int variable. I used int64_t and the problem no longer exists.

Below is link for details as I think return type of file_size needs to typecast:
https://www.codingame.com/playgrounds/5659/c17-filesystem

Related

How to save/retrieve mt19937 so that the sequence is repeated?

Here is my attempt
using namespace std;
int main()
{
mt19937 mt(time(0));
cout << mt() << endl;
cout << "----" << endl;
std::ofstream ofs;
ofs.open("/path/save", ios_base::app | ifstream::binary);
ofs << mt;
ofs.close();
cout << mt() << endl;
cout << "----" << endl;
std::ifstream ifs;
ifs.open("/path/save", ios::in | ifstream::binary);
ifs >> mt;
ifs.close();
cout << mt() << endl;
return 0;
}
Here is a possible output
1442642936
----
1503923883
----
3268552048
I expected the two last number to be the same. Obviously, I have failed to write and/or read my mt19937. Can you help fixing this code?
When you open your file for writing, you're appending to an existing file. When you read it back in, you read from the start.
Assuming you don't want to keep the existing content, change the open call to
ofs.open("/path/save", ios_base::trunc | ifstream::binary);
Using the trunc flag instead of app will truncate the existing file, so when you reopen it you're reading in the data you just wrote and not old data that was already there.

simple c++ binary file reading

I have a binary file created by some fortran code. I want to write a c++ code to read this binary file and then spit it out through std::cout. Here is so far my code:
#include<fstream>
#include<iostream>
using namespace std;
int main(){
ifstream file("tofu.txt", ios::binary | ios::in | ios::ate);
ifstream::pos_type size;
if(file.is_open()){
size = file.tellg();
cout << "size = " << size << '\n';
file.seekg(0);
char bar[500];
file.read((char*) (&bar), size);
file.close();
string foo(bar);
cout << "foo = " << foo << '\n';
}
else cout << "Unable to open file";
return 0;
}
However, when compiled and run, the code gives me nothing:
size = 250
foo =
Could someone tell me where I'm doing wrong in the code? Thanks!
You forgot to terminate your char array, leading to undefined behaviour. Fix it like this:
char bar[500];
assert(size < 500);
file.read((char*) (&bar), size - 1);
bar[size] = '\0';
(Make sure you check that size isn't larger than you have space for, too!)

regarding: instance of 'std::bad_alloc'

I read other posts but none of them helping at all,
This code have no error still there is bad_alloc error...
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char super[25];
char name[25],last_name[25];
int length;
char *sym = "#";
char *buffer;
ofstream outfile;
outfile.open("farses.dat",ios::app);
cout << "Writing to the file" << endl;
cout << "Enter your First Name: ";
cin >> name;
outfile << *sym;
outfile << name << endl;
cout << "Enter your Last Name: ";
cin >> last_name;
outfile << *sym;
outfile << last_name << endl;
cout << "Enter The Sentence : ";
cin.getline(super,25);
outfile << super << endl;
outfile.close();
ifstream infile;
infile.open("frases.dat");
infile.seekg(0, ios::end);
length = infile.tellg();
infile.seekg(0,ios::beg);
buffer = new char[length];
infile.read(buffer , length);
cout << "\n\nReading from file \n\n" << endl;
cout << buffer << endl;
infile.close();
return 0;
}
This code is terminating after coming to sentence statement..the getline() function is causing problem i guess but when i tried on other two statements(name and last_name),the getline(), it works perfectly..i even degraded the char limit to 5 too but after sentence statement is throw anyways
Thumb rule, don't fool yourself into thinking that your code has no errors. Especially when you clearly got an error. This kind of mindset will make you unable to find errors because everything you see is correct.
You never checked if your streams were open and you entered the wrong file name in the ofstream.
What happens is that, you write your data into a file name farses.dat and then you try to open a file called frases.dat (which I assume is the correct name, it means sentences).
You are getting the cursor position ifstream::tellg of an inexistent file, and it fails so the function returns -1. This is the value of length before you allocate your buffer.
When you do allocate your buffer you get a bad_alloc exception (bad_array_new_length).
Checking if your file was open would, at the very least, have saved you some debug time.
Something like this,
ifstream infile;
infile.open("frases.dat");
if ( infile.is_open() ) {
// File is open, do stuff (...)
if ( length <= 0 ) {
// Empty file / error, don't create buffer!!!
}
// (...)
infile.close();
}
else {
// Couldn't open file
}
EDIT: Fixed error explanation.

C++ ofstream - only 1 string gets written to file, previous string is overwritten, why?

i wrote a command line program that shall clean and reorganize our archived server logs by piping line by line to new target files. Each target file has an according regEx filter item so if the line that is red from the sourcefile gets written to this specific target file if it matches the regEx.
I read the regEx strings and their target file strings from a config file and save these information in vectors to be able to dynamically resize them by one with every new taget/filter pair that is red from the config.
The following piece of code shows how I loop through all my source files and for every single of them I read line by line and for every line that could be red I cycle through all the filters defined in the config and if the regEx match the line I write this line to to ofstream. Each time I do this the ofstream gets close()d and clear()ed before I open the new target file in it.
My problem now is that everything works fine except of my target files only contain 1 single string after program ends. It contains the last string that I wrote to the file.
All the strings that I wrote to the file before seem to be overwritten. I think I'm doing something wrong but I don't see what it ist.
Here's the code extract:
void StringDirector::redirect_all() {
ifstream input; //Input Filestream init
ofstream output; //Output Filestream init
string transfer; //Transfer string init
//regex e;
for (unsigned k = 0; k<StringDirector::v_sources_list.size(); k++) { //loop through all sources in v_sources_list vector
cout << endl << " LOOP through sources! Cycle #" << k << " / string is: " << StringDirector::v_sources_list[k] << endl;
input.close(); //close all open input files
input.clear(); //flush
input.open(StringDirector::v_sources_list[k].c_str()); //open v_sources_list[k] with input Filestream
if (!input) {
std::cout << "\nError, File not found: " << StringDirector::v_sources_list[k] << "\nExiting!"; //Throw error if file cannot be opened
exit(1);
}
cout << endl << " " << StringDirector::v_sources_list[k] << " opened" << endl;
getline(input, transfer); //get a first line from input Filestream and write to transfer string
while (input) { //do that as long as there is input
for (unsigned j = 0; j<StringDirector::v_filters_list.size(); j++) { //loop through all filters in v_filters_list vectord
cout << endl << " LOOP through filters! Cycle #" << j << " / string is: " << StringDirector::v_filters_list[j] << endl;
regex e(StringDirector::v_filters_list[j]);
if (regex_search(transfer, e)) {
reopen(output, StringDirector::v_targets_list[j].c_str());
output << transfer << endl;
cout << endl << " -- MATCH! Writing line to: " << StringDirector::v_targets_list[j] << endl ;
}
}
getline(input, transfer);
if (input )cout << endl << "+ got another line: " << transfer << endl;
else cout << endl << "End Of File!" << endl;
}
}
}
EDIT:
i forgot the reopen function I use
template <typename Stream>
void reopen(Stream& pStream, const char * pFile,
std::ios_base::openmode pMode = ios_base::out)
{
pStream.close();
pStream.clear();
pStream.open(pFile, pMode);
}
Try "append" open mode for your file, I guess it will be ios_base::app (see reopen function, 3rd argument).
std::ios_base::out | std::ios_base::app
You need to turn on append mode in this method by adding std::ofstream::app
input.open(StringDirector::v_sources_list[k].c_str());
should become
input.open(StringDirector::v_sources_list[k].c_str(), std::ofstream::app);
by default the mode is std::ofstream::out which starts at the beginning and overwrites everything else.
Source

How to write even numbers from sequential access file to a new sequential access files

Can someone with a little time on their hands please compile and run this code and see where I am going wrong?
#include <iostream>
#include <fstream>
using std::cout;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::ios;
int main()
{
int numbers = 0;
//create and open file
ifstream inFile;
ofstream outFile;
inFile.open ("numbers.txt", ios::in);
outFile.open ("evenNumbers.txt", ios::out);
//determine whether the file was opened
if (inFile.is_open() && outFile.is_open())
{
//read numbers file
inFile >> numbers;
while (!inFile.eof())
{
//look for even numbers
if (numbers %2 == 0)
{
outFile << numbers << endl;
//cout << numbers << endl;
}
inFile >> numbers;
}
//end while
//close files
outFile.close();
inFile.close();
cout << "Program successful. File complete." << endl;
}
//if file fails to open, display error message
else
cout << " File could not be opened " << endl;
//end if
system ("pause");
return 0;
} //end of main function
Your code has quite a few problems:
ifstream inFile;
inFile.open("numbers.txt", ios::in);
It's not exactly an error, but ios::in is the default for an ifstream, and you typically supply the file name to the constructor, something like this:
ifstream inFile("numbers.txt");
Then we have this:
getline(inFile, name);
inFile >> num;
while (inFile.eof())
while (inFile.eof()) seems to have the logic backwards -- you want to read until you reach the end of the, then quit. The rest of your loop will work (unusual for one that uses file.eof() as the condition) but is unnecessarily long and difficult to read.
//create file object and open the file
ofstream outFile;
outFile.open("updatedNumbers.txt", ios::out);
As you'd expect from the previous comment, ios::out is the default for an ofstream, and you usually give the file name to the constructor: ofstream outFile("updatedNumbers.txt");
//write the updated numbers to the file
outFile << heading << endl;
outFile << columnHeaders << endl;
outFile << underLines << endl;
heading, columnHeadders and underLines seem to be undefined variables.
for (x=0;x<20; x++)
{
if (int x%2==0)
sample[x] = x+2;
else
sample[x] = x+20;
sample also seems to be undefined.
outFile << num[x] << endl;
num also seems to be undefined. Perhaps you intended it to be the same as sample? Otherwise, you don't seem to have any code to set it to any particular value before you write it out.
Probably worse than any of that is the fact that your heading talks about writing the even numbers from one file to another, but your code doesn't seem to do anything even vaguely similar to that at all.
Well, the heading variable is undeclared, but I guess you already know that....
The error is here:
outFile << heading << endl;
outFile << columnHeaders << endl;
outFile << underLines << endl;
This is the first time you these variables heading, columnHeaders and underLines are mentioned in your program. The compiler complains because they have not been declared anywhere (Should they be int or std::string ore some other type?). Also they won't contain any useful values because nothing has been assigned to them.