How to write data to mutiple QFiles

82 Views Asked by At

I am trying to add a line to the file every time i receive data, and if the number of lines exceed 10 lines, create new files to store the data until create 5 files, but i encoutered a problem, that is the application will crash at the 56th line : QTextStream stream(current_record_file); , the code are :

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    simulateReceiveData();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::simulateReceiveData()
{
    while(file_count < 5){
        qDebug()<<"on recording ...";
        if(file_count == 1 && msg_line_count == -1){
            //create the very first new file
            record_file_name_prefix = "D:/Project/MessageRecording";
            QString record_file_name = record_file_name_prefix + "(1).asc";
            qDebug()<<"record_file_name is"<<record_file_name;
            QFile file(record_file_name);
            if (!file.open(QFile::WriteOnly | QFile::Truncate)){
                qDebug()<<QString("Fail to open file : %1").arg(record_file_name);
                return;
            }

            //write the header
            current_record_file = &file;
            QTextStream stream(current_record_file);
            stream << "START\r\n";
            msg_line_count = 0;

        }else if(msg_line_count == 10){
            //write footer to privious file
            QTextStream stream(current_record_file);
            stream << "END";
            stream.flush();
            current_record_file->close();

            //create next new file
            file_count++;
            QString record_file_name = record_file_name_prefix + QString("(%1).%2").arg(file_count).arg("asc");
            QFile file(record_file_name);
            if (!file.open(QFile::WriteOnly | QFile::Truncate))
                return;
            current_record_file = &file;  //redirect to the new created file
            msg_line_count = 0;
        }else{
            //write the main body
            QTextStream stream(current_record_file); // CRASH HERE !
            stream <<"0.0000 0 Rx 00 00 00 00 00 00 00 00\r\n";
            msg_line_count++;
        }
    }
}

mainwindow.h :

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFile>
#include <QDateTime>
#include <QTextStream>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    void simulateReceiveData();
    int file_count = 1;//number of files
    int msg_line_count = -1;//number of lines in one file
    QString record_file_name_prefix;
    QFile* current_record_file = nullptr;//point to currently written file
};
#endif // MAINWINDOW_H
2

There are 2 best solutions below

0
m7913d On

As stated by chehrlic's comment, you are accessing a (dangling) pointer to an object that has gone out-of-scope.

Two solutions exist:

  1. Reopen the file on each write (may be incompatible with QFile::Truncate and less efficient)
  2. Use QFile current_record_file as a member, instead of QFile* current_record_file. This seems to me the best approach.
0
iwtbae On

Thanks for everyone's reply, i tried m7913d's second solution, and it can create multiple QFiles now ! The magic point is after you close last QFile current_record_file, and reset its file name by current_record_file.setFileName(record_file_name);, programm will help us create new file automatically. The new worrkable code are :

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    simulateReceiveData();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::simulateReceiveData()
{
    while(file_count < 5){
        qDebug()<<"on recording ...";

        if(file_count == 1 && msg_line_count == -1){
            //create the very first new file
            record_file_name_prefix = "D:/Project/MessageRecording";
            QString record_file_name = record_file_name_prefix + QString::number(file_count) + ".asc";
            current_record_file.setFileName(record_file_name);
            if (!current_record_file.open(QFile::WriteOnly | QFile::Truncate)){
                qDebug()<<QString("Fail to open file : %1").arg(record_file_name);
                return;
            }

            //write the header
            QTextStream stream(&current_record_file);
            stream << "START\r\n";
            msg_line_count = 0;

        }else if(msg_line_count == 10){
            //write footer to privious file
            QTextStream stream(&current_record_file);
            stream << "END";
            stream.flush();
            current_record_file.close();

            file_count++;
            QString record_file_name = record_file_name_prefix + QString::number(file_count) +  ".asc";
            qDebug()<<"new record file is"<<record_file_name;
            current_record_file.setFileName(record_file_name);
            if (!current_record_file.open(QFile::WriteOnly | QFile::Truncate)){
                qDebug()<<QString("Fail to open file : %1").arg(record_file_name);
                return;
            }

            QTextStream stream2(&current_record_file);
            stream2 << "START\r\n";
            msg_line_count = 0;

        }else{
            //write the main body
            QTextStream stream(&current_record_file); // CRASH HERE !
            stream <<file_count<<" 0.0000 0 Rx 00 00 00 00 00 00 00 00\r\n";
            msg_line_count++;
            QThread::sleep(1);
        }
    }
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFile>
#include <QDateTime>
#include <QTextStream>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    void simulateReceiveData();
    int file_count = 1;//number of files
    int msg_line_count = -1;//number of lines in one file
    QString record_file_name_prefix;
    QFile current_record_file;
};
#endif // MAINWINDOW_H