Qt文件传输小记

传输文件时,简单的文本文件可以以字符串的形式传输。一般的无格式文件则以二进制格式传输。

编写程序涉及的buffer类有

QFile QByteArray QString QTCPSocket 如果用其他套接字的话还会用到 char[]数组。当传输文件时不可避免取得数据操作,存储数据类型转换,写入数据操作。

在文本方式中:

首先需要考虑字符编码,有中文字符时,得转为utf-8在通过套接字发送,另一端接收到后在转回来(QString的toutf8()和fromutf8()操作)。

考虑发送方式,是一行一行的读取和发送还是其他方式(简单的文本文件一般一行一行的传输,但是文件稍大就传输慢了)。

发送:

voidS5BSendClient::sendTextModeFile(QFile&file)

{

    QTextStreamfilestream(&file);

    QStringline=filestream.readLine();

    qDebug()<<line;

    while(!line.isNull()){

       sendFileData(line);

       line=filestream.readLine();

    }

    if(line.isNull())

    {

       if(file.isOpen())

       {

           file.close();

       }

       sendFileDone();

    }

}

voidS5BSendClient::sendFileData(QStringline)

{

    对应于文本模式的发送数据

    sendTextLineString(line);

 

}

voidS5BSendClient::sendTextLineString(QStringline)

{

    QByteArrayutf8line=line.toUtf8();

    发送4个字节的字符串长度数值

    //quint32len=(line.length()*GBKCHARSIZE)+1;

    quint32len=utf8line.length()+1;

    charlenbuf[4]={0};

    lenbuf[0]=len&0xff;

    lenbuf[1]=(len>>8)&0xff;

    lenbuf[2]=(len>>16)&0xff;

    lenbuf[3]=(len>>24)&0xff;

    send(lenbuf,4);

    发送字符串

    charlinebuf[4*1024]={0};

    strcpy(linebuf,utf8line);

    send(linebuf,len);

 

    sendedSize+=len;

    qDebug()<<tr("havesend%1/%2filedata!").arg(sendedSize).arg(m_filesize);

}


接收:
voidS5BRecvClient::recvTextFileData()

{

    charbuffer[4*1024]={0};

    recv(buffer,recvLen);

    inthasRecv=recvLen;

    QByteArrayrecvdata=QByteArray::fromRawData(buffer,recvLen);

    QStringrecvstr=QString::fromUtf8(recvdata);

    qDebug()<<recvdata;

    state=negFileDatalen;

    checkRecvState();

    //把接收的数据放到文件中

    QTextStreamout(m_pRecvfile);

    out<<recvstr<<endl;

    recvSize+=hasRecv;

    qDebug()<<tr("haverecv%1/%2data!").arg(recvSize).arg(m_filesize);

    //读完文件行数据后,在触发一次读文件行操作,用来读文件行长度

    QTimer::singleShot(0,this,SLOT(slot_readyRead()));

}


在二进制方式中:

不需要考虑编码,但是无法一行一行的传输,可以以块作单位传输。

发送:

voidS5BSendClient::sendDataModeFile(QFile&file)

{

    while(!file.atEnd())

    {

       QByteArraymax4M=file.read(4*1024);

       sendMax4MData(max4M);

    }

    if(file.isOpen())

    {

       file.close();

    }

    sendFileDone();

}

voidS5BSendClient::sendMax4MData(QByteArraymax4M)

{

    QByteArrayblock;

    QDataStreamfilestream(&block,QIODevice::WriteOnly);

    filestream.setVersion(QDataStream::Qt_4_0);

    filestream<<(quint32)0;

    filestream<<max4M;

    filestream.device()->seek(0);

    filestream<<(quint32)(block.size()-sizeof(quint32));

    getSocket()->write(block);

}


接收:

voidS5BRecvClient::recvDataFileData()

{

    charbuffer[4*1024]={0};

    recv(buffer,recvLen);

    inthasRecv=recvLen;

    //把接收的数据放到文件中

    m_pRecvfile->write(buffer,hasRecv);

    qDebug()<<m_pRecvfile->flush();

    recvSize+=hasRecv;

    qDebug()<<tr("haverecv%1/%2data!").arg(recvSize).arg(m_filesize);

    //修改状态(不需在读)

    state=negFileDatalen;

    checkRecvState();

    //尝试在读一次,或导致超时

    QTimer::singleShot(0,this,SLOT(slot_readyRead()));

 

}


两种方式传输在Qt的套接字编程时都得考虑发送和接收数据大小的协商。

也就是说发送数据前添上数据的长度,后跟该数据长度大小的数据。

接收时,先接收特定字节大小的长度值,在接收该值所表示的数据字节数。

voidS5BRecvClient::recvFileDataLen()

{

    if(!issendfile)

    {

       quint32recvdatalen;

       charbuffer[4]={0};

       recv(buffer,recvLen);

       if(!isLittleEndian())

       {

           recvdatalen=charToUInt8(buffer[0])+

                    charToUInt8(buffer[1])*256+

                    charToUInt8(buffer[2])*256*256+

                    charToUInt8(buffer[3])*256*256*256;

       }else

       {

           recvdatalen=charToUInt8(buffer[3])+

                    charToUInt8(buffer[2])*256+

                    charToUInt8(buffer[1])*256*256+

                    charToUInt8(buffer[0])*256*256*256;

       }

       qDebug()<<recvdatalen;

       state=negFileData;

       recvLen=recvdatalen;

       //读完文件行长度后,在触发一次读数据操作,用来都文件行数据

       QTimer::singleShot(0,this,SLOT(slot_readyRead()));

    }

}

boolS5BRecvClient::isLittleEndian()

{

    unionuni{

       inti;

       charc;

    }test;

    test.i=1;

    return(test.c==1);

}

quint8S5BRecvClient::charToUInt8(chara)

{

    quint8r=a-'\0';

    qDebug()<<r;

    returnr;

}

voidS5BRecvClient::recvFileData()

{

    if(!issendfile)

    {

       if(m_mode==TextMode)

       {

           recvTextFileData();

       }elseif(m_mode==DataMode)

       {

           recvDataFileData();

       }

    }

}


完整的代码示例http://download.csdn.net/detail/wenwenxiong/8338007

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值