I have a text file with article numbers with their expiration date.
Example:
123456789 21-9-2014
987654321 7-12-2014
112233445 3-2-2015
But I want a list of all articles that are going to expire in 6 weeks (42 days) in a QTextEdit widget. So I tested this with just a QDate widget to check if something is almost expired or not.
QDate ExpireDate = ui->date->date();
if (ExpireDate.toJulianDay() - today.toJulianDay() <= 42)
{
qDebug() << "Expired";
}
This worked. But I want all the articles that are almost expiring (6 weeks before) and stored in text file to be displayed in a textEdit widget. But I don't know how to 'find' these articles in a text file and to display them.
For the sample file you provided, I would do the following:
QFile file1("test.txt");
if (!file1.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QDate today = QDate::currentDate();
while (!file1.atEnd()) {
QByteArray line = file1.readLine();
QList<QByteArray> tokens = line.split(' '); // Depends on the file format.
Q_ASSERT(tokens.size() == 2);
QString dateString = tokens.at(1).trimmed();
QDate date = QDate::fromString(dateString, "d-M-yyyy");
Q_ASSERT(date.isValid());
if (date.toJulianDay() - today.toJulianDay() <= 42) {
fprintf(stdout, "Expired\n");
}
}
Related
Im try to add to my sketch a dynamic way to setup the ethernet info (mac, ip, gateway, subnet) from a configuration file (config.txt). So running a webserver and serving htm files from sd card, user can go to setting page, fill a form with these info and when posted , the webserver parse the http form and save (update) the config.txt file. After that system do a restart, in order to start with the new settings (by read the config.txt file)
I have create succesfully all the parts (sd, ethernet, webserver, webclient, create the config file from posted form data) except the get params by reading the config.txt file.
I can read line by line the config, I can split the line to param & value, and now I need to fill some byte variables with the readed data. I can (after a month of google searching) to read IPs (decimal values) to byte array. Im stack to read the MAC ADDRESS hex into byte array. The config file contains the:
mac=8f:2c:2b:19:e0:b7;
ip=192.168.1.200;
netmask=255.255.255.0;
gateway=192.168.1.254;
dns=8.8.8.8;
posturl=192.168.1.157;
postport=8080;
postscript=/itherm/update.php;
interval=60000;
and the code that I use to read is:
byte myMAC[6];
byte myIP[4];
File fset;
fset = SD.open("config.txt");
if (fset){
char ff[40];
while (fset.available()>1){
bool eol=false;
for (int i=0; !eol;i++){
ff[i]=fset.read();
if (ff[i]=='\n'){
eol=true;
}
}
String par="";
bool DONE=false;
for (int i=0; !DONE;i++){
par+=ff[i];
if (ff[i]== '='){DONE=true;}
}
String pval="";
DONE=false;
//------------------------
if (par=="ip=" ){
int x=0;
while(!DONE){
for(int i=3;i<=i+21;i++){
if(ff[i]=='.'){
myIP[x]=pval.toInt();
x++;
i++;
pval="";
}
else if(ff[i]==';' || i>20){
myIP[x]=pval.toInt();
DONE=true;
break;
}
pval+=ff[i];
}
}
}
} //while (fset.available()>1)
} //if (fset)
I will appreciate any help. Please no answers with simple use of Serial.print(). I have found hundreds of suggestions but none, that work properly to read all the parameters (dec, hex, strings). After a month of effort & searching, I wonder why something so necessary and useful does not exist as an example in the community, completely functional !!
Best regards
Okay so here is a complete set of routines to do what you want -I think you misunderstood the concept of char arrays vs a single char[0] The routines are documented and self explanatory. I recomend not to finish lines with ; but with '\n' which in your example is there anyway (also you can not see the new line terminator) To get the mac address I need three lines:
if (strncmp(cfgLine, "mac=", 4) == 0) {
strcpy (macAddr, cfgLine + 4);
}
line one compares the first 4 characters and if it is 0 (meaning its a fit)
line two copies the chars from the fifth to the last char from the lineBuffer to the target array, which can actually be used as param for functions.
The file structure should be with no ; as you would have to parse ; and \n
mac=8f:2c:2b:19:e0:b7
ip=192.168.1.200
....
postport=8080
To convert a char array to eg int we use atoi(), to convert a single char[0] to a single number we use int singleDigit = char[0]-48;
const char configurationFilePath [] = "/someconfig.txt";
char cfgLine[128] = {'\0'}; // this is a global temp char array to hold the read lines (lenght= chars longest line +1)
char numBuffer[16] = {'\0'}; // this is a global temo char array to help to convert char to number
char macAddr [18] = {'\0'}; // this is a global char array to hold the mac address
char ipAddr [16] = {'\0'}; // this is a global char array to hold the IP address - max xxx.xxx.xxx.xxx
int postport=0;
// .... you can easyly implement for all other data you want to store/retrieve
// Counts the lines of a file
uint16_t countLines() {
uint16_t currentLineCount = 0;
File cfgFile = SD.open(configurationFilePath, "r");
if (!cfgFile) {
Serial.println(F("Config file open failed on read"));
} else {
while (cfgFile.available()) {
/** Lets read line by line from the file */
if (cfgFile.read() == '\n') currentLineCount ++; // Lines are delimited by '\n'
}
cfgFile.close();
}
return currentLineCount;
}
//Load the config file from SD/SPIFFS/LittleFS
bool loadConfigFile() {
uint16_t lineCounter = countLines();
if (lineCounter <= 0) {
Serial.print(F("No config data stored in file ")); Serial.println(configurationFilePath);
return false;
}
else {
File cfgFile = SD.open(configurationFilePath, "r");
while (cfgFile.available()) {
strcpy (cfgLine, (cfgFile.readStringUntil('\n').c_str())); // normaly you use new line, we copy one line at a time
// Serial.println(cfgLine); /** Printing for debuging purpose */
while (cfgLine[0] != '\0') { /* Block refilling of cfgLine till processed */
loadSingleCfgLine();
}
}
cfgFile.close();
Serial.println(F("[Success] Loaded config !"));
return true;
}
}
//Load the data of a single line into a char array
void loadSingleCfgLine() {
if (strncmp(cfgLine, "mac=", 4) == 0) {
strcpy (macAddr, cfgLine + 4);
}
if (strncmp(cfgLine, "ip=", 3) == 0) {
strcpy (ipAddr, cfgLine + 3);
}
if (strncmp(cfgLine, "postport=", 9) == 0) {
strcpy (numBuffer, cfgLine + 9);
postport = atoi(numBuffer); // One extra step to convert to int
}
// ... easy to implement for all other data
}
I divided the routines into small independend functions, so its easy adaptable for different uses. I'm sorry for not digging into your code as it is hard to follow and unclear what you want todo.As an added bonus we do not use the String class. These Strings tend to fragment heap - causing resets/crashes while the global char arrays are compiled to flash and don't show this behavior.
I have to parse a big file with several thousand records. I want to display a progress bar, but I do not know the number of recordings in advance. Do I have to roll over this file twice?
The first to know the number of recording.
The second to perform the treatment
Or is there a more simple way to get the number of records without going through the entire file before I process ?
My code snippet :
void readFromCSV(const QString &filename){
int line_count=0;
QString line;
QFile file(filename);
if(!file.open(QFile::ReadOnly | QFile::Text))
return;
QTextStream in(&file);
while(!in.atEnd()){ //First loop
line = in.readLine();
line_count++;
}
while (!in.atEnd()) { //Second loop
...
line = in.readLine();
process();
...
}
}
Thank you for help
This question is different from the one here : counting the number of lines in a text file
1) The loop process is already done. In this case it is prevention of double shooting.
2) The code is a QT one, not a C++ fonction to add as a redundancy
I think there is no way to count lines without reading the file at least once. To avoid it I wouldn't rely on the number of lines, but rather on how much data I have been read. Here is how I would solve this problem:
QFile file(fileName);
file.open(QFile::ReadOnly | QFile::Text);
const auto size = file.size();
QTextStream in(&file);
while (!in.atEnd()) {
auto line = in.readLine();
// Process line.
// [..]
// Calculate the progress in percent.
auto remains = file.bytesAvailable();
auto progress = ((size - remains) * 100) / size;
printf("progress: %d%%\r", progress);
}
I have 2 QDateEdit which are Date_dob and Date_doj.
I am storing the value using a Qstring shown below.
QString str_dob(ui->DATE_dob->text());
QString str_doj(ui->DATE_doj->text());
Now i want to populate the same into ui->Date_dob and ui->Date_doj (after some editing event takes place). I have used ,
ui->DATE_dob->setText(s.at(2));
ui->DATE_doj->setText(s.at(5)); //where s is a string having data
but the data doesn't populate.
Any kind of suggestion will be extremely appreciated.
Thanks in advance
For convert QString to QDate you can use QDate::fromString(). Then you can set date in QDateEdit with QDate::setDate(const QDate &date).
Hope it help.
You use wrong way the conversion.
QDate to QString
QString str_dob = ui->DATE_dob->toString("dd MM yyyy");
in the date format you should specify it else your conversation is default format. Known Format you can use
QString to QDate
if( ui->DATE_dob->setDate(QDate::fromString(str_dob,"dd MM yyyy").year()\
,QDate::fromString(str_dob,"dd MM yyyy").month()\
,QDate::fromString(str_dob,"dd MM yyyy").day()){
// Your Conversation Succes
}
when QString to QDate you have to know date format in string else your conversation fail or wrong value you get.
Example: if Qstring is : 19/12/2017 than your format is "dd/MM/yyyy"
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am creating a GUI for windows PC. I want to store a series of images on the PC. The name of the images is identical. But I want to append them with timestamps. So, how to save image using timestamp in Qt?
in addition to that, the images shud be saved something like this example:
referenceImage<.date.><.time.>jpg
where date and time correspond to the date on and time at which the image was saved on the windows PC. I have tried the following too
Here i have implemented this at the click of a push button:-
void MainWindow::on_generateImagePushButton_clicked()
{
QDate date = QDate::currentDate();
QString dateString = date.toString();
QString path = QString("E:\\QT1\\timeStampTrial\\goldenRefImg[%1].jpg").arg(dateString);
qDebug()<<"path: "<<path;
/*display current time*/
QTime time = QTime::currentTime();
QString timeString = time.toString();
QString path2 = QString("E:\\QT1\\timeStampTrial\\goldenRefImg[%1 %2].jpg").arg(dateString).arg(timeString);
qDebug()<<"path2: "<<path2;
/*converting from QString to char* */
QByteArray bA = path2.toLocal8Bit();
const char *c_charArray = bA.data();
/*saving image*/
IplImage *imgWithTimeStamp = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
cvSaveImage(c_charArray, imgWithTimeStamp);
}
The image gets saved with dateStamp, ie eg. goldenRefImg[Wed Feb 5 2014].jpg when I use string-path. But when I use string-path2, it does NOT save with dateStamp & timeStamp as i expect it to, i.e. goldenRefImg[Wed Feb 5 2014 10:47:32].jpg
But the qDebug statements showing path and path2 are displayed correctly.
Application Output:
Starting E:\QT1\timepass-build-desktop-Qt_4_8_1_for_Desktop_-_MSVC2010__Qt_SDK__Debug\debug\timepass.exe...
path: "E:\QT1\timeStampTrial\goldenRefImg[Wed Feb 5 2014].jpg"
path2: "E:\QT1\timeStampTrial\goldenRefImg[Wed Feb 5 2014 10:47:23].jpg"
Now i have just recollected that an image cannot be saved with special characters such as the colon : which's there in timeStamp. Can the time format be changed?
I tried this way:
path2.replace(":","-");
But the E:\ also gets converted into E-.Please guide. Thank u.
const QDateTime now = QDateTime::currentDateTime();
const QString timestamp = now.toString(QLatin1String("yyyyMMdd-hhmmsszzz"));
const QString filename = QString::fromLatin1("/some/path/someimage-%1.jpg").arg(timestamp);
This takes the current date/time, converts it to a string using QDateTime::toString() (the documentation lists the formatting options) and constructs the file name out of it.
Then just use filename with QImage::save() or QImageWriter.
/*display current date*/
QDate date = QDate::currentDate();
QString dateString = date.toString();
QString path = QString("E:\\QT1\\timeStampTrial\\goldenRefImg[%1].jpg").arg(dateString);
qDebug()<<"path: "<<path;
/*display current time*/
QTime time = QTime::currentTime();
QString timeString = time.toString();
QString path2 = QString("E:\\QT1\\timeStampTrial\\goldenRefImg[%1 %2].jpg").arg(dateString).arg(timeString);
qDebug()<<"path2: "<<path2;
path2.replace(":","-");
path2.replace(1,1,":");
QByteArray bA = path2.toLocal8Bit();
const char *c_charArray = bA.data();
IplImage *imgWithTimeStamp = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
cvSaveImage(c_charArray, imgWithTimeStamp);
Thank you for all your suggestions #Dmitri Sazonov and #Frank Osterfeld
I have the same code in 2 different projects. The Qstring::number(data.toLong(&ok,2),16) works in one project and in the other project it does not work. Does anyone know what the reason could be? The code is as follows
1) unsigned short status;
2) long int setting;
3) bool ok;
4) QString data_selected;
5) data_selected = lineEdit_data->text(); //get the binary value
6) data_selected = QString::number(data_selected.toLong(&ok, 2), 16); //convert binary value to hex value
7) setting = data_selected.toLong(&ok, 16); //convert string to integer
In line 5 I am getting data from a lineEdit. This line works fine. I just inserted a new text edit box and displayed the data there and there I can see data. I have data as "1000000000001000". Then I execute line 6, the output of which is '8008' in first case and '0' in the other project. This is the problem. The code is exactly the same. I have copied and pasted. But in debugging I can see this difference. Please can anyone tell me why this is happening?
I thought that comment under answer was clear.
Correct code like this to detect what is the problem:
ulong setting;
bool ok;
data_selected = data_selected.trimmed(); // first try without this line
ulong value = data_selected.toULong(&ok, 2);
if (ok) {
data_selected = QString::number(value, 16);
setting = data_selected.toULong(&ok, 16);
} else {
data_selected = "convertion error";
}