QT文件存储

8 篇文章 0 订阅

本例子利用线程进行缓冲存储

QFileSaveThead.h
/*************************************************************************
接口描述:文件存储类
拟制:
接口版本:V1.0
时间:20220922
说明:利用线程和缓存进行文件存储
*************************************************************************/

#ifndef QFILESAVETHREAD_H
#define QFILESAVETHREAD_H
#include <QFile>
#include <QMutex>
#include <QQueue>
#include <QThread>
#include <qsemaphore.h>

class QFileSaveThread : public QThread
{
    Q_OBJECT
public:
    explicit QFileSaveThread(short nCacheMax = 100, QObject *parent = nullptr);
    ~QFileSaveThread();

protected:
    volatile bool m_bStop;
    QMutex m_mutex;
    QMutex m_mutexQueue;
    QSemaphore m_freeSpace;
    QSemaphore m_usedSpace;
    QQueue<TDataBuffer> m_queueDataBuffer;
    QFile m_file;     //存储文件
    unsigned int m_nCacheSize; //缓存大小默认1MB
    unsigned short m_nCacheMax;//最大缓冲块数目
    byte *m_pBuffer;  //缓存数据
    unsigned int m_nWritePos;  //写入位置
    bool m_bOpen;
    QString m_qsFilePath;
    int m_nFaileAllocateCount;//分配内存失败次数
    long long m_llWriteSize;//写入字节数

private:
    void ClearBuf(void); //清除Buffer

public:
    bool CreatFile(QString qsFilePath); //打开文件
    unsigned int GetCacheSize() const;//获得缓冲块大小
    void SetCacheSize(int nCacheSize);//设置缓冲块大小
    unsigned int GetCacheMax() const;//获得最大缓冲块数目
    long long WriteFile(byte *pBuffer, int nLen); //写文件
    void CloseFile();                        //关闭写文件
    long long GetWriteSize();//获得写入字节数

    // QThread interface
protected:
    virtual void run() override;
};

#endif // QFILESAVETHREAD_H
QFileSaveThead.cpp
#include "qfilesavethread.h"
#include <QDebug>
#include <QDir>

QFileSaveThread::QFileSaveThread(short nCacheMax, QObject *parent)
    : QThread(parent)
    , m_freeSpace(nCacheMax)
    , m_nCacheMax(nCacheMax)
{
    m_bStop = false;
    m_nCacheSize = 1 * 1024 * 1024; //1MB
    m_pBuffer = nullptr;
    m_nWritePos = 0;
    m_nFaileAllocateCount = 0;
    m_bOpen = false;
    m_llWriteSize = 0;
    start(QThread::TimeCriticalPriority);
}

QFileSaveThread::~QFileSaveThread()
{
    m_mutexQueue.lock(); //进入临界区
    m_bStop = true;
    m_usedSpace.release();
    this->wait();
    m_mutexQueue.unlock(); //离开临界区
    CloseFile();
    ClearBuf();
}

unsigned int QFileSaveThread::GetCacheSize() const
{
    return m_nCacheSize;
}

void QFileSaveThread::SetCacheSize(int nCacheSize)
{
    QMutexLocker locker(&m_mutex);
    m_nCacheSize = nCacheSize;
}

unsigned int QFileSaveThread::GetCacheMax() const
{
    return m_nCacheMax;
}

long long QFileSaveThread::WriteFile(byte *pBuffer, int nLen)
{
    if(m_nFaileAllocateCount >= 10)
        return m_llWriteSize;
    QMutexLocker locker(&m_mutex);
    if (!m_file.isOpen())
        return m_llWriteSize;
    if (m_pBuffer == nullptr) {
        m_pBuffer = new (std::nothrow) byte[m_nCacheSize];
        if(m_pBuffer == nullptr)
        {
            qDebug() << "Failed to allocate memory.";
            m_nFaileAllocateCount++;
        }
        m_nWritePos = 0;
    }
    if (m_pBuffer!= nullptr)
    {
        if(m_nWritePos + nLen < m_nCacheSize) {
            memcpy(m_pBuffer + m_nWritePos, pBuffer, nLen);
            m_llWriteSize += nLen;
            m_nWritePos += nLen;
        } else //写入数据
        {
            bool bCopy = false;
            if (m_nWritePos + nLen == m_nCacheSize) {
                memcpy(m_pBuffer + m_nWritePos, pBuffer, nLen);
                m_llWriteSize += nLen;
                m_nWritePos += nLen;
                bCopy = true;
            }
            TDataBuffer tDataBuffer;
            tDataBuffer.pBuffer = m_pBuffer;
            tDataBuffer.nLen = m_nWritePos;
            if (m_freeSpace.tryAcquire()) {
                m_mutexQueue.lock(); //进入临界区
                m_queueDataBuffer.append(tDataBuffer);
                //qDebug() << m_queueDataBuffer.size();
                m_mutexQueue.unlock(); //离开临界区
                m_usedSpace.release(); //消费锁释放
            } else {
                qDebug()
                        << "----------The storage file queue is too long to be reproduced!----------\r";
            }
            m_pBuffer = new (std::nothrow) byte[m_nCacheSize];
            if(m_pBuffer == nullptr)
            {
                qDebug() << "Failed to allocate memory.";
                m_nFaileAllocateCount++;
            }
            //缓存不够拷贝,将本包拷贝至下一次缓冲区
            if (m_pBuffer!= nullptr && !bCopy) {
                memcpy(m_pBuffer, pBuffer, nLen);
                m_llWriteSize += nLen;
                m_nWritePos = nLen;
            } else
                m_nWritePos = 0;
        }
    }
    return m_llWriteSize;
}

void QFileSaveThread::CloseFile()
{
    m_bOpen = false;
    m_mutexQueue.lock(); //进入临界区
    while (!m_queueDataBuffer.empty()) {
        TDataBuffer tDataBuffer = m_queueDataBuffer.dequeue();
        if (tDataBuffer.pBuffer != nullptr) {
            if (m_file.isOpen())
            {
                m_file.write((char *) tDataBuffer.pBuffer, tDataBuffer.nLen);
            }
            delete[] tDataBuffer.pBuffer;
        }
    }
    m_mutexQueue.unlock(); //离开临界区
    QMutexLocker locker(&m_mutex);
    if (m_pBuffer != nullptr) {
        if (m_file.isOpen())
            m_file.write((char *) m_pBuffer, m_nWritePos);
        delete[] m_pBuffer;
        m_pBuffer = nullptr;
        m_nWritePos = 0;
    }
    if (m_file.isOpen()) {
        if (m_file.size() == 0)
            m_file.remove();
        m_file.close();
    }
}

long long QFileSaveThread::GetWriteSize()
{
    return m_llWriteSize;
}

void QFileSaveThread::ClearBuf()
{
    QMutexLocker locker(&m_mutex);
    while (!m_queueDataBuffer.empty()) {
        TDataBuffer tDataBuffer = m_queueDataBuffer.dequeue();
        if (tDataBuffer.pBuffer != nullptr)
            delete[] tDataBuffer.pBuffer;
    }
    if (m_pBuffer != nullptr)
        delete[] m_pBuffer;
}

bool QFileSaveThread::CreatFile(QString qsFilePath)
{
    m_qsFilePath = qsFilePath;
    QMutexLocker locker(&m_mutex);
    if (m_file.isOpen())
        m_file.close();
    m_file.setFileName(qsFilePath);
    QString qsDir = qsFilePath.left(qsFilePath.lastIndexOf("/"));
    if(qsDir == qsFilePath)
    {
        qsDir = qsFilePath.left(qsFilePath.lastIndexOf("\\"));
    }
    QDir qDir;
    qDir.mkpath(qsDir);
    m_bOpen = m_file.open(QIODevice::Append | QIODevice::ReadWrite);
    qDebug() << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<";
    qDebug() << "Creat save file" << qsFilePath;
    qDebug() << "Cache size is" << m_nCacheSize << "byte";
    qDebug() << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<";
    m_llWriteSize = 0;
    return m_bOpen;
}

void QFileSaveThread::run()
{
    while (!m_bStop) {
        m_usedSpace.acquire();
        if (m_bStop)
            return;
        while (!m_bStop && !m_queueDataBuffer.empty()) {
            m_mutexQueue.lock(); //进入临界区
            TDataBuffer tDataBuffer = m_queueDataBuffer.dequeue();
            //qDebug() << m_queueDataBuffer.size();
            m_mutexQueue.unlock(); //离开临界区
            m_freeSpace.release();
            //处理数据
            if (tDataBuffer.pBuffer != nullptr) {
                if (m_file.isOpen())
                {
                    m_file.write((char *) tDataBuffer.pBuffer, tDataBuffer.nLen);
                }
                delete[] tDataBuffer.pBuffer;
            }
        }
    }
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值