I want to some text to output to a file. I heard that it is better to stream the data rather than creating a large string and outputing that. Presently I am creating a large string and outputing to a file. Request to provide an sample code on how to stream a data and write to a file using C++.
Thanks!
#include <fstream>
int main()
{
std::ofstream fout("filename.txt");
fout << "Hello";
fout << 5;
fout << std::endl;
fout << "end";
}
Your file now contains this:
Hello5
end
See more info on std::ofstream for details.
HTH
File writing already uses buffering. If it is not efficient for you, you can actually modify the filebuf, eg increase its size or use a custom one.
Avoid doing unnecessary flushes of your buffer, which is done with endl. That is the most "abused" feature of file-writing.
The simplest way to create a file-stream for outputting is:
#include <fstream>
int main( int argc, char * argv[])
{
if( argc > 1 )
{
std::ofstream outputFile( argv[1] );
if( outputFile )
{
outputFile << 99 << '\t' << 158 << '\n'; // write some delimited numbers
std::vector< unsigned char > buf;
// write some data into buf
outputFile.write( &buf[0], buf.size() ); // write binary to the output stream
}
else
{
std::cerr << "Failure opening " << argv[1] << '\n';
return -1;
}
}
else
{
std::cerr << "Usage " << argv[0] << " <output file>\n";
return -2;
}
return 0;
}
Related
I'm trying to dump the contents of a file to cout.
#include <iostream>
#include <fstream>
int main(int argc, char** argv)
{
if (argc > 1) {
std::ifstream fin(argv[1]);
if (fin) {
std::cout << "---file contents---\n";
std::cout << fin.rdbuf();
std::cout << "---end contents---\n";
} else {
std::cout << "The file does not exist\n";
}
}
else {
std::cout << "Usage: " << argv[0] << " FILE\n";
}
if (std::cout.good()) {
return 0;
}
else if (std::cout.fail()) {
return 1;
}
else {
return 2;
}
}
This code does not work as intended when the input file is empty. It prints the initial "---file contents---", but never prints the trailing "---end contents---". After debugging, I found the application is not crashing, but instead is putting std::cout in an error state (the return code is 1).
How can I print the contents of an empty file without putting cout in an error state?
This operator<< reference (overload number 10 in the list) explains it all:
If no characters were inserted, executes setstate(failbit).
Since the input file is empty, there's no characters to insert into the output stream. And the failbit is set.
You need to add a specific check for failbit after
std::cout << fin.rdbuf();
to see if the input file was empty or not.
Please look at this code first, then I will ask my question.
#include <bits/stdc++.h>
#include <fstream>
using std::cout;
using std::cin;
using std::endl;
int main() {
std::ofstream out_file ("outfile.txt"); /* creates a outfile.txt */
if (!out_file) { // checks files existence
std::cerr << "Error bruh!" << endl;
return (1);
}
int num = 100;
double total = 456.78;
std::string name = "atik";
out_file << num << "\n" // writing to the file
<< total << "\n"
<< name << endl;
/* Reading from file, because i want to! - */
std::ifstream in_file("outfile.txt"); // will open outfile for reading.
char c;
while (in_file.get(c)) {
cout << c;
}
/*
Output (as expected) -
100
456.78
atik
Right Now My **output.txt** file is - (as expected)
100
456.78
atik
*/
/* Appending the file that we just created - */
std::ofstream out_file2 ("outfile.txt", std::ios::app);
cout << "\nEnter something to write in file : " << endl;
std::string line;
getline(cin, line);
out_file2 << line; // writes to out_file2
/* Reading from file again - */
std::ifstream in_file2("outfile.txt"); // will open outfile.txt for reading.
if( !in_file2 ) {
std::cerr << "File didn't open. Error encountered." << endl;
}
char ch;
cout << endl;
while( in_file2.get(ch) ) {
cout << ch;
}
/*
Output (unexpected? why?)-
100
456.78
atik
*/
in_file.close();
in_file.close();
out_file.close();
out_file2.close();
return 0;
}
Now, my outfile..txt is - (as expected):
100
456.78
atik
Hello there
Then why is the output for in_file2 not showing Hello there? Why does it truncate the Hello there? Can someone please explain?
out_file2<<line;
doesn't flush (the use of std::endl in the prior code does), so if there's less than a full block of data read from std::cin, the data written to out_file2 is likely stuck in your user-mode buffers (and not visible when you open the file for read independently). Those buffers make I/O efficient by reducing the number of system calls when you're performing many smallish writes, in exchange for any buffered data not being visible outside of that file handle until the buffer is flushed (implicitly by filling, or explicitly by manual flushing or closing the file handle).
Simply changing that line to:
out_file2 << line << std::flush;
(or just .close()ing out_file2 once you're done with it) will cause it to flush properly and you should see the new data on opening it again for read.
I open the mp3 file by mistake with notepad++ ( Open with ) and show the entire file in text inside the notepad it was so cool.
since I am learning c++ again, I told myself let write a program that opens any file inside the console and display their content on the console so I begin my code like this :
int readAndWrite() {
string filename(R"(path\to\a\file)");
ifstream file(filename);
string line;
if (!file.is_open()) {
cerr << "Could not open the file - '"
<< filename << "'" << endl;
return EXIT_FAILURE;
}
while (getline(file, line)){
cout << line;
}
return EXIT_SUCCESS;
}
but it only shows 3 or 4 lines of the file and then exits the program I check my notepad++ again and find out about 700,000 line is in there.
I told myself maybe there is a character inside the file so I start writing the above code with the below changes. instead of displaying the file let's wrote inside a text file.
int readAndWrite() {
string filename(R"(path\to\a\file)");
string filename2(R"(path\to\a\file\copy)");
ifstream file(filename);
ofstream copy(filename2);
string line;
if (!file.is_open()) {
cerr << "Could not open the file - '"
<< filename << "'" << endl;
return EXIT_FAILURE;
}
while (getline(file, line)){
copy << line;
}
return EXIT_SUCCESS;
}
and again the same results. next try I give up on reading the file line by line so I start copying with this function.
void copyStringNewFile(ifstream& file, ofstream& copy)
{
copy << file.rdbuf();
}
and their results did not change a bit.
At this point, I told myself the problem is from file maybe and it is kinda is because when I use a simple text file all of the above codes work.
Like all other non-text files, mp3 files don't contain lines so you shouldn't use std::getline. Use istream::read and ostream::write. You can use istream::gcount to check how many characters that was actually read.
Since you are dealing with non-text files, also open the files in binary mode.
You should also test if opening both files works - that is, both the input and the output file.
Example:
#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>
int readAndWrite() {
std::string filename(R"(path\to\a\file)");
std::string filename2(R"(path\to\a\file_copy)");
std::ifstream file(filename, std::ios::binary);
if(!file) {
std::cerr << '\'' << filename << "': " << std::strerror(errno) << '\n';
return EXIT_FAILURE;
}
std::ofstream copy(filename2, std::ios::binary);
if(!copy) {
std::cerr << '\'' << filename2 << "': " << std::strerror(errno) << '\n';
return EXIT_FAILURE;
}
char buf[1024];
while(file) {
file.read(buf, sizeof(buf));
// write as many characters as was read above
if(!copy.write(buf, file.gcount())) {
// write failed, perhaps filesystem is full?
std::cerr << '\'' << filename2 << "': " << std::strerror(errno) << '\n';
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
int main() {
return readAndWrite();
}
IN IOS app, module written in C++ I am writing my data (map of basic strings and integers) to a text file. Using following method:
bool Recognizer::saveMap(const char * s)
{
if(trainingData.model && !trainingData.model.empty()) {
const string filename = string(s);
std::ofstream file(s, ios_base::trunc );
try{
if(! file.is_open())
{
file.open(s);
}
for (map<String,int>::iterator it=trainingData.idMap.begin(); it!=trainingData.idMap.end(); ++it)
{
cout << it->second << " " << it->first << endl;
file << it->first << endl << it->second << endl;
}
file.close();
}
catch(cv::Exception & e){
if(file.is_open())
file.close();
int code = e.code;
string message = e.err;
cerr << "cv::Exeption code: " << code << " " << message << endl;
return false;
}
std::streampos fileLength = iosFileSize(s);
cout << "Saved map to: " << filename << " length: " << fileLength << endl;
return true;
}
return false;
}
My contains one entry and console output indicates that two lines: string, string representing number have been written to my file.
Subsequent opening file for reading and reading using getline or using stream operator indicates that file is empty:
bool Recognizer::loadMap(const char * s)
{
std::streampos fileLenght = iosFileSize(s);
std::ifstream file(s, ios::in);
try{
if(file.is_open())
{
string name;
string lineName;
string lineTag;
int tag;
int count = 0;
while(getline(file,name))
{
if(getline(file,lineTag))
{
tag = stoi(lineTag,0,10);
count++;
cout << tag << " " << name << endl;
trainingData.idMap[name]=tag;
trainingData.namesMap[tag]=name;
}
}trainingData.personsCount=count;
file.close();
}
}
catch(cv::Exception & e){
if(file.is_open())
file.close();
int code = e.code;
string message = e.err;
cerr << "cv::Exeption code: " << code << " " << message << endl;
return false;
}
cout << "Loaded map from: " << s << " lenght: "<< fileLenght << endl;
return true;
}
I also copied from one of stackoverflow answers method returning file lenght and using it to verify lenghth of the file after write operation:
std::streampos iosFileSize( const char* filePath ){
std::streampos fsize = 0;
std::ifstream file( filePath, std::ios::binary );
fsize = file.tellg();
file.seekg( 0, std::ios::end );
fsize = file.tellg() - fsize;
file.close();
return fsize;
}
The file path passed to saveMap and loadMap seems to be legit. With path that the app could not write to, attempt to write caused exception.
There are no errors returned by write operation but both, attempts to read and iosFileSize() indicate that file is empty.
I am not sure if i need call file.open() and file.close() or file is open and closed automatically when output stream is created and later goes out of scope.
I experimented with those with the same result ( call to file.is_open returns true so the block calling file.open() is skipped.
What am I doing wrong?
I appreciate all responses.
It does not seem like you call file.flush(); anywhere in Recognizer::saveMap() after writing to the file stream. std::ofstream::flush() saves changes you've made to the file. Add file.flush(); between when you make changes to the code and when you close the file. See if that remedies your issue.
I also had the same issue. Using file.flush() everytime after you insert to a file can save your file.
However if you insert something like this, say,
file << "Insert This"; You will need to add file.flush().
But some people have issues, like if you just insert file << "Insert This" << endl; , this works fine. The key point here is that, std::endl calls flush() everytime it is used internally. you can say it is a shortend form of "\n" + flush().
I believe from looking at your code that you are overwriting your data when you open the file in the second program you should be using something like this.
std::fstream fs;
fs.open ("test.txt", ios::app)
instead of doing the ios::in
I am trying a reasonably simple program to test binary input/output. I am basically writing a file with a header (string) and some data (doubles). The code is as follows:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
typedef std::ostream_iterator<double> oi_t;
typedef std::istream_iterator<double> ii_t;
std::ofstream ofs("data.bin", std::ios::in);
//-If file doesn't exist, create a new one now
if(!ofs) {
ofs.open("data.bin", std::ios::out|std::ios::binary|std::ios::app);
}
else {
ofs.close();
ofs.open("data.bin", std::ios::out|std::ios::binary|std::ios::app);
}
//-Write a header consisting of length of grid subdomain and its name
///*
const std::string grid = "Header";
unsigned int olen = grid.size();
ofs.write(reinterpret_cast<const char*>(&olen), sizeof(olen));
ofs.write(grid.c_str(), olen);
//*/
//-Now write the data
///*
std::vector<double> data_out;
//std::vector<std::pair<int, int> > cell_ids;
for(int i=0; i<100; ++i) {
data_out.push_back(5.0*double(i) + 100.0);
}
ofs << std::setprecision(4);
std::copy(data_out.begin(), data_out.end(), oi_t(ofs, " "));
//*/
ofs.close();
//-Now read the binary file; first header then data
std::ifstream ifs("data.bin", std::ios::binary);
///*
unsigned int ilen;
ifs.read(reinterpret_cast<char*>(&ilen), sizeof(ilen));
std::string header;
if(ilen > 0) {
char* buf = new char[ilen];
ifs.read(buf,ilen);
header.append(buf,ilen);
delete[] buf;
}
std::cout << "Read header: " << header << "\n";
//*/
///*
std::vector<double> data_in;
ii_t ii(ifs);
std::copy(ii, ii_t(), std::back_inserter(data_in));
std::cout << "Read data size: " << data_in.size() << "\n";
//*/
ifs.close();
//-Check the result
///*
for(int i=0; i < data_out.size(); ++i) {
std::cout << "Testing input/output element #" << i << " : "
<< data_out[i] << " " << data_in[i] << "\n";
}
std::cout << "Element sizes: " << data_out.size() << " " << data_in.size() <<
"\n";
//*/
return 0;
}
The problem is that when I try to write and read (and then print) both the header and the data it fails (I confirmed that it doesn't read the data then, but displays the header correctly). But when I comment out one of the write sections (header and/or data), it displays that part correctly indicating the read worked. I am sure I am not doing the read properly. Perhaps I am missing the usage of seekg somewhere.
The code runs fine for me. However you never check if the file is successfully opened for writing, so it could be silently failing on your system. After you open ofs you should add
if (!ofs) {
std::cout << "Could not open file for writing" << std::endl;
return 1;
}
And the same thing after you open ifs
if (!ifs) {
std::cout << "Could not open file for reading" << std::endl;
return 1;
}
Or something along those lines. Also I do not understand why you check if the file exists first since you do the same whether it exists or not.
This should work
#include <iostream>
using std::cout;
using std::cerr;
using std::cin;
using std::endl;
#include <fstream>
using std::ifstream;
#include <cstdint>
int main() {
ifstream fin;
fin.open("input.dat", std::ios::binary | std::ios::in);
if (!fin) {
cerr << "Cannot open file " << "input.dat" << endl;
exit(1);
}
uint8_t input_byte;
while (fin >> input_byte) {
cout << "got byte " << input_byte << endl;
}
return 0;
}