Appending a new line in a file(log file) in c++ - c++

I have a logging functionality and in this I have got log files. Now every time I run the program I want that previously written file should not get deleted and should be appended with the current data (what ever is there in the log file)
Just to make it clear for example: I have a log file logging_20120409.log which keeps the timestamp on a daily basis. Suppose I run my project it writes to it the current timestamp. Now if I rerun it the previous timestamp gets replaced with it. I do not want this functionality. I want the previous time stamp along with the current time stamp.
Please help

You want to open the file in "append" mode, so it doesn't delete the previous contents of the file. You do that by specifying ios_base::app when you open the file:
std::ofstream log("logfile.txt", std::ios_base::app | std::ios_base::out);
For example, each time you run this, it will add one more line to the file:
#include <ios>
#include <fstream>
int main(){
std::ofstream log("logfile.txt", std::ios_base::app | std::ios_base::out);
log << "line\n";
return 0;
}
So, the first time you run it, you get
line
The second time:
line
line
and so on.

Use something like:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ofstream out("try.txt", ios::app);
out << "Hello, world!\n";
return 0;
}
The ios:app option makes the output get appended to the end of the file instead of deleting its contents.

maybe you need to open the file with the append option. like this:
FILE * pFile;
pFile = fopen ("myfile.txt","a");
or this :
fstream filestr;
filestr.open ("test.txt", fstream::app)

Related

text file is not being opened for reading purposes

Before you flag this as a duplicate post and refer me on how to correctly open a text file and print to the console, I have looked at numerous StackOverflow posts about this topic and cannot find a solution for myself.
I am trying to open a text file I created (currently in the same project folder as my main.cpp), read the text, and print it to the console. I go through the if file is open statement fine but the while loop does not go through even once. I will post the function below. Please suggest any changes or ideas on how to correctly call and open/read the text file. (and I would prefer not to call the exact file location of the text file for this to work ex. C://example/textFile.txt/ Though I have not tried this method yet, I'd prefer avoiding it)
Also, I am using CLion IDE from jetbrains, C++17, and Ninja to build.
printing text file to console fucntion
#include <iostream>
#include <iomanip>
#include <iomanip>
#include <fstream>
#include <string>
#include <stdlib.h>
#include "printTest.h"
void printTest::print() {
std::string line; //string that holds the line of a text file
std::ifstream textFile("test.txt", std::ios::in); //file creation
if(textFile.is_open()) //checking if file was opened
{
while(std::getline(textFile, line))
{
//std::getline(textFile, line);
std::cout << line << "\n";
}
} else { //this is always printing i.e. file is not correctly being opened for reading
std::cout <<"Unable to open the text file..." <<std::endl; //Prints if file was not opened
}
textFile.close();
}

Input Output with fstream

Can anyone tell me what is wrong with this code? I always get not open.
#include <iostream>
#include <fstream>
using namespace std;
int main(){
fstream fs;
fs.open("fsfile2",ios::in|ios::out|ios::binary);
if(fs.is_open()){
fs.write("wow",sizeof("wow"));
char str[20];
fs.read((char*)str,sizeof(str));
cout<<str<<endl;}
else
cout<<"Not open\n";
return 0;
}
Try this code
fs.open("fsfile2", ios::app|ios::in|ios::out|ios::binary);
By using the open() like you are that file will not be created if that is your goal.
If you want to create a new file please look at: fstream won't create a file
If the file exists, you are not looking for it in the right path. Or change the file name to the full path or put the executable in the folder where the file is.
Hope this helps.
Probably, you do not have permissions to create files in the directory, where your executable is.
Solution:
Please add a file extension to the filename.
If it's a text file, it will be
"fsfile2.txt"
Then, I tried removing
ios::in
since the first process only writes to file, and by removing that, the file is created and "wow" is also written at it.
In order for these lines
fs.read((char*)str,sizeof(str));
cout<<str<<endl;
to work,
You need to close the stream after writing to it, then open the stream in read mode, then read the contents. Take note that closing the stream will save the edited file.
Additional:
You can also change
fs.write("wow",sizeof("wow"));
to
fs << "wow";
You can do the same when reading from file,
fs >> str;
You can also use the string class of C++, instead of char array so that the number of characters inside the file won't be your problem anymore.
#include <string>
string str;
Checking for EOF (end-of-file) is recommended since files are read line by line. Once you add a new line and add a character to the line, the code that doesn't loop until EOF will only read the first line of the file.
In order to solve this, it is recommended to loop until EOF is reached.
while(!fs.eof()) {
fs >> str;
cout << str << endl;
}
So here is the improved snippet:
#include <string>
fs.open("fsfile2.txt", ios::out); // ios::out for write only
if(fs.is_open()) {
// writes "wow" to file
fs << "wow";
// closes the file
fs.close();
// ios::in for read only
fs.open("fsfile2.txt", ios::in);
// better to define variable just before using it
string str;
// loops until end-of-file
while(!fs.eof()) {
// reads a line from file, stores it to str
fs >> str;
// shows str to screen
cout << str << endl;
}
}
*Note: I removed
ios::binary
Since your code is not dealing with binary files yet.
I tried these and it worked fine! Have a nice day!
fstream fs; does not create a new file for you.
You need to make sure that the file exists in your project directory.
On the other hand, if you were to use ofstream fs("file.txt"); it would create the file for you. Or use only ios::out when you open fstream fs, this will create the file for you.

read and write a binary file in c++ with fstream

I'm trying to write simple c++ code to read and write a file.
The problem is my output file is smaller than the original file, and I'm stuck finding the cause.
I have a image with 6.6 kb and my output image is about 6.4 kb
#include <iostream>
#include <fstream>
using namespace std;
ofstream myOutpue;
ifstream mySource;
int main()
{
mySource.open("im1.jpg", ios_base::binary);
myOutpue.open("im2.jpg", ios_base::out);
char buffer;
if (mySource.is_open())
{
while (!mySource.eof())
{
mySource >> buffer;
myOutpue << buffer;
}
}
mySource.close();
myOutpue.close();
return 1;
}
Why not just:
#include <fstream>
int main()
{
std::ifstream mySource("im1.jpg", std::ios::binary);
std::ofstream myOutpue("im2.jpg", std::ios::binary);
myOutpue << mySource.rdbuf();
}
Or, less chattily:
int main()
{
std::ofstream("im2.jpg", std::ios::binary)
<< std::ifstream("im1.jpg", std::ios::binary).rdbuf();
}
Two things: You forget to open the output in binary mode, and you can't use the input/output operator >> and << for binary data, except if you use the output operator to write the input-streams basic_streambuf (which you can get using rdbuf).
For input use read and for output use write.
There are 3 problems in your code:
1- You have not opened your output file in Binary.
2- Your code return "1", normally you should return "0", if something went wrong then return an error code.
3- You should use "manipulators" and make c++ not to avoid whitespaces, so in order to read from file instead of:
mySource >> buffer;
you should use:
mySource >> std:noskipws >> buffer;
Well, its just because of padding at the end of the image. eof of any file do not include the padded bytes added at the end of file.
Try this
take img1.jpg contains 20 space charecter at the end not visible here (uegfuyregwfyugwrerycgerfcg6ygerbucykgeugcrgfrgeyf ) and run your program (do not include parenthesis in the file, these are used to show the data content)
you will see img2.jpg contains (uegfuyregwfyugwrerycgerfcg6ygerbucykgeugcrgfrgeyf)
So, its better option to read the file byte by byte using the filesize which you can get using stat, and run for loop till filesize. Hope this should resolve your problem you mentioned above

C++ edit a binary file with another

Solved! thanks all of you very much. My day has been made!(well morning, its 4am)
I'm trying to write a program in C++ that opens a .dat file in binary and replaces the first 1840 hex characters with that of another .dat file, while leaving the remaining hex values of the first .dat file the same. I have spent about 12 hours on this today and have had little success. I am a beginner programmer, I have taken one semester worth of c++ courses and we did not get to streams.
(it opens a file and everything, but deletes every thing after the new values have been added)
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <cstring>
using namespace std;
int main (){
string filename;
long size;
char* memblock;
cout << " Enter a file to be modded by Mod.dat ";
cin >> filename;
ofstream infile ( filename ,std::ofstream::binary);
//filename: the file that will be opened and changed)
ifstream modFile ("Mod.dat", ifstream::binary);
// (mod.dat is the file that i get the first 1840 hex values from)
modFile.seekg (0,modFile.end);
size = modFile.tellg();
memblock = new char [size];
modFile.seekg (0, ios::beg);
modFile.read (memblock, size);
infile.write(memblock, 1840);
modFile.close();
infile.close();
cout << endl;
return 0;
}
Any help would be greatly appreciated, I hope there is some simple way to do this.
Solved! thanks all of you very much. My day has been made!(well morning, its 4am)
Edit:
You can modidy your file in place with something like :
std::fstream s(my_file_path, std::ios_base::binary);
s.seekp(position_of_data_to_overwrite, std::ios_base::beg);
s.write(my_data, size_of_data_to_overwrite);
std::fstream will not truncate your input file as std::ofstream does.
The other solution is to not use the same file for reading and writing. Use three files :
One for the output file.
One for the First input file.
One for the second input file.
fstream infile ( filename ,std::ofstream::binary); does not keeps the contents of the original file. Everything you write will erase the contents of the file.
Thus, you should:
open the output file
open the "Mod" file, read the first 1840 bytes from the first file, write them into the output file.
open the "main input file" file, move the cursor to 1840, read the remaining data and write it to the output file.
Depending on the "main input file" size, you may want to buffer you read/write operation.
My preferred fix, although Matthieu Rouget's fix does indeed work, is to just add ofstreeam::in to the opening of the input file:
ofstream infile ( filename.c_str(), std::ofstream::binary | ofstream::in);
(I had to use c_str() in my build, as glibc in my version doesn't take std::string as input).
I tested this on my local system (it took a while to realize that mod.dat is actually "Mod.dat"!)
It is probably a good idea to also check that the files actually opened, so something like this after ofstream infile line:
if (!infile)
{
cout << "Couldn't open " << filename << endl;
}
and similar for the modfile line.
And since you go through the effort of figuring out what the first part of the modfile size is, I would suggest that you also USE that for the writing of the file.

overwriting some text in a file using fstream and delete the rest of the file

I am trying to write a program that read a file using fstream
then, rewrite some of the text and delete the rest of the file
This the code that I am trying to do
#include<iostream>
#include<fstream>
using namespace std;
int main(int argc, char **argv){
fstream *binf;
fstream someFile("t.txt", ios::binary|ios::out|ios::in);
int i;
for(i=0;i<3;i++){
char c;
someFile.seekg(i);
someFile.get(c);
cout<<"c:"<<c<<endl;
}
someFile.seekp(i++);
someFile.put("Y");
someFile.seekp(i++);
someFile.put("Y");
//Delete the rest of the file
return 0;
}
Note the following flags for opening a file
ios::in Open for input operations.
ios::out Open for output operations.
ios::binary Open in binary mode.
ios::ate Set the initial position at the end of the file. If this flag is not set to any value, the initial position is the beginning of the file.
ios::app All output operations are performed at the end of the file, appending the content to the current content of the file. This flag can only be used in streams open for output-only operations.
ios::trunc If the file opened for output operations already existed before, its previous content is deleted and replaced by the new one.
I try many combinations of these but non of them help me to do what I want
I want to read the file until I find text. If I find the text that I want, I over write it and delete the rest of the file. So, the file should be re-sized to smaller file.
You can't do that with single stream object.
Possible solutions:
Either close your file and call truncate function, :
#include <unistd.h>
int ftruncate(int fildes, off_t length);
int truncate(const char *path, off_t length);
MS Windows version of truncate is _chsize - see http://msdn.microsoft.com/en-us//library/dk925tyb.aspx
int _chsize(
int fd,
long size
);
Or open your file for reading only, read/replace to some stringstream, then put everything to your file this time opened for overwriting:
fstream someFile("t.txt", ios::binary|ios::in);
stringstream ss;
// copy (with replacing) whatever needed from someFile to ss
someFile.close();
someFile.open("t.txt", ios::binary|ios::out|ios::trunc);
someFile << ss.rdbuf();
someFile.close();