Qt关于遇到0x00提前结束的问题

目录

Qt关于遇到0x00提前结束的问题

假如有如下一个文件,数据中包含大量的0x00

Qt关于遇到0x00提前结束的问题_第1张图片

1、使用QFile读取文件

QFile firmwarefile(filePath);
firmwarefile.open(QIODevice::ReadOnly);
//方法1:全部读取
QByteArray ba =  firmwarefile.readAll();   //正确
//方法2:读一行,指定长度
char buf[1024];
qint64 lineLength;
lineLength =  firmwarefile.readLine(buf, sizeof(buf));   //正确,此时不要debug看buf里面的数据,因为0x00的存在,在debug中只能看到前两个字节
//方法3:读指定长度到缓冲区
int num = 1024*1;//每次读取固件大小
char *sendBuffer=new char[num]();
lineLength = firmwarefile.read(sendBuffer, num);   //正确,此时不要debug看sendBuffer里面的数据,因为0x00的存在,在debug中只能看到前两个字节
delete [] sendBuffer;
firmwarefile.close();

2、使用FILE读取文件

QFileInfo fileInfo = QFileInfo(filePath);
QString fileName = fileInfo.fileName();
std::string str = filePath.toStdString();
FILE *fp;
fopen_s(&fp, str.c_str(), "r");
char *dataBuffer = new char[fileInfo.size()]();   
fread(dataBuffer, fileInfo.size(), 1, fp);      //正确,此时不要debug看dataBuffer里面的数据,因为0x00的存在,在debug中只能看到前两个字节

delete [] dataBuffer;
fclose(fp);       

3、QByteArray转char *

如果将文件数据读取到了QByteArray中,需要将QByteArray的数据取出时,可以采用如下两种方法

方法1:

QByteArray ba = firmwarefile.readAll();
char *dataBuffer = new char[ba.size()]();
memcpy(dataBuffer, ba.data(), ba.size());
qDebug() << ba.size() =  << ba.size();
for (int i = 0; i < ba.size(); i++) {
    qDebug() << dataBuffer[i];
}

方法2:

QByteArray ba = firmwarefile.readAll();
char *data = ba.data();
while(*data)   //错误,while循环遇到第一个0x00即结束
{
    qDebug() << *data;
    ++data;
}
for (int i = 0; i < ba.size(); i++) {      //正确,可完整输出QByteArray中的内容
    qDebug() << data[i];
}

4、写入probuf

假如在生成的probuf中有如下两个重载函数

inline void FirmwareInfo::set_firmwarefile(const char* value) {
    GOOGLE_DCHECK(value != nullptr);
  
  firmwarefile_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:FirmwareInfo.firmwareFile)
}
inline void FirmwareInfo::set_firmwarefile(const void* value, size_t size) {
    firmwarefile_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast(value), size));
  // @@protoc_insertion_point(field_set_pointer:FirmwareInfo.firmwareFile)
}

要将含有0x00的char数组放入probuf中时,只能调用第二个重载函数

FirmwareInfo *firmwareInfo=new FirmwareInfo();
firmwareInfo->set_firmwarefile(sendBuffer, length);    //其中length为数组的大小

如果调用第一个重载函数,probuf中只能写入0x00以前的数据,0x00之后的数据丢失

5、char *转QByteArray

QByteArray ba = firmwarefile.readAll();
char *dataBuffer = new char[ba.size()]();
memcpy(dataBuffer, ba.data(), ba.size());
//方法1:指定长度
QByteArray sendData = QByteArray(dataBuffer, ba.size());     //正确
//方法2:
QByteArray sendData = QByteArray(dataBuffer);     //错误,sendData中只包含0x00以前的数据

6、socket发送

对于tcp通信,没有特别要求,均可正确写入缓冲区

方法1:
int fd = tcpConnect->write(sendData);    //正确
方法2:
int fd = tcpConnect->write(sendData,sendData.length()));    //正确

 

总结:处理含有大量0x00的数据,指定数据长度很重要!

你可能感兴趣的:(Qt,qt,c++)