Qt多线程场景下实现将其他线程数据写入定时生成的TXT文件
解决方案:跨线程数据累计与每分钟批量写入文件
嘿,我来帮你搞定这个问题!你的核心需求是把TCP客户端线程每秒接收的数据累计起来,每分钟一次性写入对应时间命名的TXT文件里。目前文件是空的,问题出在你没有累计存储所有收到的数据,每次只写了最后一次覆盖的Data变量,而且没有建立数据的持续缓存机制。
核心解决思路
我们需要给每个客户端线程添加一个数据缓存容器,用来临时存储每分钟内收到的所有数据,等到QTimer触发写入时,再把缓存里的所有数据一次性写入文件,最后清空缓存准备下一轮数据收集。
修改后的代码实现
1. 更新mythread.h,添加数据缓存和线程安全锁
#ifndef MYTHREAD_H #define MYTHREAD_H #include <QObject> #include <QTcpSocket> #include <QThread> #include <QDebug> #include <QStringList> #include <QMutex> class MyThread : public QThread { Q_OBJECT public: explicit MyThread(qintptr ID, QObject *parent = 0); void run(); signals: void error(QTcpSocket::SocketError socketerror); void sendValue(QString strValue); void close(QString disconnectId); private slots: void readyRead(); void disconnected(); void InitThreadObjects(); void sendData(); private: QTcpSocket *socket; qintptr socketDescriptor; QByteArray Data; QStringList dataBuffer; // 新增:存储每分钟的所有数据 QMutex mutex; // 新增:确保缓存操作的线程安全 }; #endif // MYTHREAD_H
2. 修改mythread.cpp,实现数据累计与批量写入
#include "mythread.h" #include <QThread> #include <QTimer> #include <QTime> #include <QFile> #include <QString> #include <QTextStream> MyThread::MyThread(qintptr ID, QObject *parent) : QThread(parent) { this->socketDescriptor = ID; } void MyThread::run() { qDebug() << " Thread started"; socket = new QTcpSocket(); if(!socket->setSocketDescriptor(this->socketDescriptor)) { emit error(socket->error()); return; } connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection); connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected())); connect(this, &MyThread::started, this, &MyThread::InitThreadObjects); qDebug() << socketDescriptor << "Client connected"; QString strValue = QString::number(socketDescriptor); emit sendValue(strValue); exec(); } void MyThread::readyRead() { Data = socket->readAll(); qDebug() << socketDescriptor << " Data in: " << Data; socket->write(Data); // 新增:将收到的数据加入缓存(加锁确保线程安全) QMutexLocker locker(&mutex); dataBuffer.append(Data); } void MyThread::disconnected() { qDebug() << socketDescriptor << " Disconnected"; QString disconnectId = QString::number(socketDescriptor); emit close(disconnectId); socket->deleteLater(); exit(0); } void MyThread::InitThreadObjects(){ QTimer *timer = new QTimer(this); connect(timer,SIGNAL(timeout()),this,SLOT(sendData())); timer->start(60000); } void MyThread::sendData(){ QTime currentTime = QTime::currentTime(); QString time = currentTime.toString("hhmmss"); QString filename = "/home/pi/"+time+".txt"; qDebug() << filename; QFile file(filename); if(!file.open(QFile::WriteOnly | QFile::Text)) { qDebug() << "Could not open file for writing"; return; } QTextStream out(&file); // 新增:批量写入所有缓存的数据 QMutexLocker locker(&mutex); for(const QString& data : dataBuffer) { out << data << "\n"; // 每条数据换行,便于查看 } // 清空缓存,准备下一分钟的数据收集 dataBuffer.clear(); file.flush(); file.close(); }
关键修改点说明
- 数据缓存容器:用
QStringList dataBuffer来存储每分钟内收到的所有数据,避免每次收到新数据覆盖旧数据。 - 线程安全锁:用
QMutex和QMutexLocker确保在多线程环境下(比如同时读写缓存)的操作安全,虽然这里每个客户端是独立线程,但加锁是良好的编程习惯。 - 批量写入逻辑:在
sendData中遍历缓存列表,把所有数据写入文件后清空缓存,确保下一分钟的数据不会和上一分钟混淆。
这样修改后,你的TCP客户端线程每秒收到的数据会被累计存储,每分钟QTimer触发时,就会把这一分钟内的所有数据一次性写入对应时间命名的TXT文件里啦!
内容的提问来源于stack exchange,提问作者김덕래




