I wanted to make an Attendance system which would take system date and time as file name of the file for ex:
this is how normally it is
int main () {
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
cout << (now->tm_year + 1900) << '-'
<< (now->tm_mon + 1) << '-'
<< now->tm_mday
<< endl;
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
}
but i want system date and time in place of example.txt
i have calculated time by including ctime header file in the program above program is just example .
You can use strftime() function to format time to string,It provides much more formatting options as per your need.
int main (int argc, char *argv[])
{
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
char buffer [80];
strftime (buffer,80,"%Y-%m-%d.",now);
std::ofstream myfile;
myfile.open (buffer);
if(myfile.is_open())
{
std::cout<<"Success"<<std::endl;
}
myfile.close();
return 0;
}
#include <algorithm>
#include <iomanip>
#include <sstream>
std::string GetCurrentTimeForFileName()
{
auto time = std::time(nullptr);
std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%F_%T"); // ISO 8601 without timezone information.
auto s = ss.str();
std::replace(s.begin(), s.end(), ':', '-');
return s;
}
Replace std::localtime* with std::gmtime* if you work together abroad.
Usage e.g.:
#include <filesystem> // C++17
#include <fstream>
#include <string>
namespace fs = std::filesystem;
fs::path AppendTimeToFileName(const fs::path& fileName)
{
return fileName.stem().string() + "_" + GetCurrentTimeForFileName() + fileName.extension().string();
}
int main()
{
std::string fileName = "example.txt";
auto filePath = fs::temp_directory_path() / AppendTimeToFileName(fileName); // e.g. MyPrettyFile_2018-06-09_01-42-00.log
std::ofstream file(filePath, std::ios::app);
file << "Writing this to a file.\n";
}
*See here for a thread-safe alternative of those functions.
You could try using ostringstream to create a date string (as you're doing with cout), then use it's str() member function to retrieve the corresponding date string.
You can use stringstream class for this purpose, for example:
int main (int argc, char *argv[])
{
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
stringstream ss;
ss << (now->tm_year + 1900) << '-'
<< (now->tm_mon + 1) << '-'
<< now->tm_mday
<< endl;
ofstream myfile;
myfile.open (ss.str());
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
return(0);
}
Related
I am trying to write a parser to read large text file in C++. Similar python code using readtable method is approximately 7 to 8 times faster.
I am wonder why it runs so slow in C++. Most of the time is taken in using istringstream to parse lines to separate table numbers. It will be great if someone can point issue with code or alternative to istringstream. The code is as below:
'''
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <chrono>
using namespace std::chrono;
int main()
{
auto start = high_resolution_clock::now();
std::ifstream inf{ "/Users/***/some.bed" };
std::istringstream iss;
int aprox_nlines = 7000000;
std::vector<int>* ptr_st = new std::vector<int>();
std::vector<int>& start_v = *ptr_st;
start_v.reserve(aprox_nlines);
std::vector<int>* ptr_en = new std::vector<int>();
std::vector<int>& end_v = *ptr_en;
end_v.reserve(aprox_nlines);
// If we couldn't open the output file stream for reading
if (!inf)
{
// Print an error and exit
std::cerr << "Uh oh, File could not be opened for reading!" << std::endl;
return 1;
}
int count=0;
std::string line;
int sstart;
int end_val;
std::string val;
if (inf.is_open())
{
while (getline(inf, line))
{
count += 1;
iss.str(line);
iss >> val;
iss >> sstart;
start_v.push_back(sstart);
iss >> end_val;
end_v.push_back(end_val);
}
std::cout << count<<"\n";
inf.close();
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
std::cout << "Time taken by function: " << duration.count() << " microseconds" <<"\n";
return 0;
}
'''
It seems using FILE * = fopen() it runs much better. It is around 10 times faster than istringstream. Compared to python inbuilt (readtable) function it is 33% faster.
'''
FILE * ifile = fopen("*/N.bed", "r");
size_t linesz = 60+1;
char * nline = new char[linesz];
char T[50], S[50];
int sn,en;
unsigned int i = 0;
while(getline(&nline, &linesz, ifile) > 0) {
i++;
//std::cout<<nline<<"\n";
sscanf(nline, "%s %d %d", T, &sn, &en);
start_v.push_back(sn);
end_v.push_back(en);
//std::cout<<T<<" "<< S <<"\n";
}
'''
So, I want to create a log file for an app I am trying to create and I don't know how to name the log to something like "log/date&time"
Anyway, here is my code:
#include <iostream>
#include <fstream>
#include <time.h>
#include <stdio.h>
#include <sstream>
using namespace std;
int main (int argc, char *argv[])
{
time_t t = time(0);
struct tm * now = localtime( & t );
char buffer [80];
strftime (buffer,80,"%Y-%m-%d.",now); //i think i can't just put "log/%Y-%m-%d." there.
ofstream myfile;
myfile.open ("log/" + buffer); // this is my problem, i can't put the ' "log/" + ' part there
if(myfile.is_open())
{
cout<<"Success"<<std::endl;
}
return 0;
}
You should use std::string which supports concatenation via the overloaded operator+.
std::string buffer(80, '\0');
strftime( &buffer[0], buffer.size(), "some format string", now);
/* ... */
std::ofstream myfile( ("log/" + buffer).c_str() );
// Remove the (..).c_str() part when working with a C++11 conforming
// standard library implementation
you actual question is "why doesnt this work"
myfile.open ("log/" + buffer);
answer - because c++ doesnt support what you want - concatenate a string literal with a char * and return another char *.
do
std::string filetime(buffer);
std::string filename = "log/" + filetime;
open(filename.c_str());
Consider using std:: facilities instead (std::string and std::ostringstream come to mind):
std::ostream& time_digits(std::ostream& out, unsigned int digits)
{ // convenience function: apply width and fill for the next input
return out << std::setw(digits) << std::setfill('0');
}
std::string unique_log_name()
{ // generate unique log name, depending on local time
// example output: "log/2014-04-19.log"
auto now = time(0);
tm *ltm = localtime(&now);
std::ostringstream buffer;
buffer
<< "log/" << time_digits(4) << ltm.tm_year
<< "-" << time_digits(2) << ltm.tm_mon
<< "-" << time_digits(2) << ltm.tm_day;
// could also add these to the name format:
// buffer
// << "-" << time_digits(2) << ltm.dm_hour
// << "-" << time_digits(2) << ltm.tm_min
// << "-" << time_digits(2) << ltm.tm_sec;
buffer << ".log"; // add extension
return buffer.str();
}
void client_code()
{ // construct log stream on unique file name
ofstream myfile{ unique_log_name() };
if(myfile)
{
cout << "Success" << std::endl;
}
}
I have a code that i want it to get input file from command line and create output file with XXX at the end - meanning if intput= "blabla.txt" or "/johny/first/blabla.txt" i till get "blablaXXX.txt" or "/johny/first/blablaXXX.txt"
The second question is that when i find a line i was looking for i want to copy only the numbers (keep in date mode) and the len
Line will be "IT IS HERE time 12:04:56.186, len 000120"
And i want to get in the new file line: 12:04:56.186 120
#include <iostream>
#include <fstream>
using namespace std;
int main( int argc, char* args[] )
{
string inputName=args[1];
ifstream inputName(inputFileName);
////// here i will need to get the output string name some thing like
// string outputFileName=EDITED_INPUT_NAME+"XXX"+".txt";
ofstream outpuName(outputFileName);
while( std::getline( inputName, line ) )
{
if(line.find("IT IS HERE") != string::npos)
// how to make it take only the parts i need??????
outpuName << line << endl;
cout << line << endl;
}
inputName.close();
outpuName.close();
return 0;
}
Does this solve your problem:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int main(int argc, char* args[]) {
ifstream inputFile(args[1]);
// Your first problem
string outputFileName(args[1]);
outputFileName.insert(outputFileName.find("."), "XXX");
cout << "Writing to " << outputFileName << endl;
// End of first problem
ofstream outputFile(outputFileName.c_str());
string line;
while (getline(inputFile, line)) {
if (line.find("IT IS HERE") != string::npos) {
// Your second problem
string::size_type time_start = line.find("time ") + 5;
string::size_type time_end = line.find(",", time_start);
cout << time_start << " " << time_end << endl;
string time = line.substr(time_start, time_end - time_start);
string::size_type len_start = line.find("len ") + 4;
string::size_type len_end = line.find(" ", len_start);
if (len_end != string::npos)
len_end += 4;
int len = atoi(line.substr(len_start, len_end - len_start).c_str());
// End of second problem
outputFile << time << " " << len << endl;
cout << time << " " << len << endl;
}
}
inputFile.close();
outputFile.close();
return 0;
}
Example input:
sdfghjk sdfghjk fghjkl
IT IS HERE time 12:04:56.186, len 000120
usjvowv weovnwoivjw wvijwvjwv
IT IS HERE time 12:05:42.937, len 000140
Example output:
12:04:56.186 120
12:05:42.937 140
The code could look nicer with std::regex and auto, but as this wasn't tagged with C++11, I held back.
I need to create file with specific file name format (on windows). the format is:
Name_nodeNum_frequency.txt
nodeNum is int and frequency is float.
those two variables should be written with fixed digits:
if nodeNum is 8 --> 008
if frequency is 4.88421 --> 4.884
this is the function:
create_file(int nodeNum, double frequency)
{
char buffer [50];
//convert int to string
itoa(nodeNum, buffer, 10);
string sNodeNum = string(buffer);
//not sure about the double
//tried to_string but I got:
// more than instance of overloaded function matches the argument list
string fileName = ("Name_" + sNodeNum + "_" + sfreq + "MHZ");
FILE* pFile = OpenFile(fileName);
}
I tried to use %d, but it seems like I should not do that:
string fileName = ("Delay_" + "%3d" + "_" + sfreq + "MHZ" , sNodeNum);
I will be happy for some guidance.
thanks!
You seem to be mixing C and C++ here. A simple way to do this in C would be:
#include <stdio.h>
int main()
{
int sNodeNum = 8;
double sfreq = 4.88421;
char filename[50];
sprintf(filename, "Delay_%03d_%.3fMHZ.txt", sNodeNum, sfreq);
FILE* pFile = fopen(filename, "w");
return 0;
}
If on the other hand, if you want to use C++, you should make a few changes:
#include <iomanip>
#include <fstream>
#include <sstream>
#include <iostream>
int main()
{
int sNodeNum = 8;
double sfreq = 4.88421;
std::ostringstream ss;
ss << "Delay_" << std::setfill('0') << std::setw(3) << sNodeNum
<< "_" << std::setprecision(4) << sfreq << "MHZ.txt";
std::string filename(ss.str());
std::ofstream fout(filename.c_str());
return 0;
}
Each of these two approaches opens a file for writing, with the name Delay_008_4.884MHZ.txt.
Live demo link
#include <string>
#include <iomanip>
#include <iostream>
int nodeNum = 8;
float frequency = 4.88421f;
std::ostream& out = std::cout; // put your std::ofstream file or std::ostringstream
std::ios::fmtflags flags = out.flags();
out.width(3);
out.fill('0');
out.setf(std::ios::right, std::ios::adjustfield);
out << nodeNum << std::endl;
flags = out.flags(flags);
out.precision(3);
out.setf(std::ios::fixed, std::ios::floatfield);
out << frequency;
out.flags(flags);
Or even simpler:
out << std::setw(3) << std::setfill('0') << std::right << nodeNum << std::endl;
out << std::setprecision(3) << std::fixed << frequency;
Output:
008
4.884
Code(main.cpp) (C++):
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
//general vars
std::ofstream ofs;
std::ifstream ifs;
std::stringstream ss;
//spamFiles vars
std::string defPath;
int defAmt;
void spamFiles(std::string paramPath);
int main(int argc, const char * argv[])
{
srand(time_t(NULL));
std::cout << "Enter the amount of files: ";
std::cin >> ::defAmt;
std::cout << "Now enter the target path: ";
std::cin >> ::defPath;
::spamFiles(::defPath);
std::cout << defAmt << " files were created." << std::endl;
return 0;
}
void spamFiles (std::string paramPath){
//system("open -a Terminal .");
for(int i = 0; i < ::defAmt; i++){
std::string tempS;
int ranNum = rand() % 501;
ss << ranNum;
std::string ssResult = ss.str();
std::string finalPath = ::defPath + ssResult + ".txt";
ifs.open(finalPath);
if(ifs.good()){
finalPath += "dupe.txt";
while(ifs.good()){
finalPath += "dupe.txt";
ifs.open(finalPath);
}
}
ofs.open(finalPath);
ofs << "";
ofs.close();
ss.str(std::string());
}
return;
}
My problem is following.
Whenever I run this and enter, lets say 53 as for the amount, in the end it'll never create the full amount of files. It's always scaled.
Here's an example.
Defined Amont: 300 -> What I Get: 240
Defined Amount: 20 -> What I get: 15
Defined Amount: 600 -> What I get: 450
Thanks in advance.
Based on the logic of your code, you are creating a file if your ifstream object is not 'good()'. If some files aren't being created, then the error lies here.
With some digging, you'll find that the constructor for an ifstream object does not take a string, but instead a char *.
Adding a c_str() to your 'finalPath' variable should take care of this issue.
Some things to note:
You've forgotten to include fstream and iostream.
When digging into problems like this, don't use random numbers as your first test case. It was easier for me to replicate your issue by just trying to create files in numerical order.
Also don't forget 'close()' your ifstreams!
My adaptation of the code:
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
#include <fstream>
#include <iostream>
//general vars
std::ofstream ofs;
std::ifstream ifs;
std::stringstream ss;
//spamFiles vars
std::string defPath;
int defAmt;
void spamFiles(std::string paramPath);
int main(int argc, const char * argv[])
{
srand(time_t(NULL));
std::cout << "Enter the amount of files: ";
std::cin >> ::defAmt;
std::cout << "Now enter the target path: ";
std::cin >> ::defPath;
::spamFiles(::defPath);
std::cout << defAmt << " files were created." << std::endl;
return 0;
}
void spamFiles (std::string paramPath){
//system("open -a Terminal .");
for(int i = 0; i < ::defAmt; i++){
std::string tempS;
int ranNum = rand() % 501;
ss << ranNum;
std::string ssResult = ss.str();
std::string finalPath = ::defPath + ssResult + ".txt";
ifs.open(finalPath.c_str());
while(ifs.good()){
finalPath += "dupe.txt";
ifs.open(finalPath.c_str());
}
ifs.close();
std::cout << finalPath << std::endl;
ofs.open(finalPath.c_str());
ofs << "";
ofs.close();
ss.str(std::string());
}
return;
}