2013-11-18 4 views
1

Недавно я запрограммировал передачу файлов с помощью Qt. Думал, что это сработало, мне все еще интересно, что случилось. Пожалуйста, помогите мне выяснить причину. Большое спасибо. ?Размер QByteArray сложно вычислить?

Почему размер головы больше, чем сумма SizeOf (qin32), SizeOf (qint32) и длина имени файла (я предполагаю, что это является причиной функции - SetVersion())

QFileInfo info(file_to_send.fileName()); 
QByteArray head; 
QDataStream out(&head, QIODevice::WriteOnly); 
out.setVersion(QDataStream::Qt_5_0); 
out << qint32(file_to_send.size() + info.fileName().length() + sizeof(qint32)*2) 
    << qint32(info.fileName().length()) 
    << info.fileName(); 
tcpClient.write(head); 
+0

Глава клиента Размер: 40 | Клиентский заголовок: [252592] [14] ["Screenshot.png"] – Leo

ответ

1

Вы сделали это сложным. Картина такова:

QFileInfo info(file_to_send.fileName()); 
QByteArray head; 
QDataStream out(&head, QIODevice::WriteOnly); 
out.setVersion(QDataStream::Qt_5_0); 
out << qint32(0) 
    << info.fileName(); // << YouCanAddMoreStuffHere; 

out.device()->seek(0); 
out << qint32(out.length()); 

tcpClient.write(head); 

и читать код:

void SomeClass::slotReadClient() { // slot connected to readyRead signal of QTcpSocket 
    QTcpSocket *tcpSocket = (QTcpSocket*)sender(); 
    QDataStream clientReadStream(tcpSocket); 

    while(true) { 
     if (!next_block_size) { 
      if (tcpSocket->bytesAvailable() < sizeof(qint32)) { // are size data available 
       break; 
      } 
      clientReadStream >> next_block_size; 
     } 

     if (tcpSocket->bytesAvailable() < next_block_size) { 
      break; 
     } 
     QString fileName; 
     clientReadStream >> fileName; // >> YouCanAddMoreStuffHere; // same as above 

     next_block_size = 0; 
    } 
} 
+0

Ну, вы оставили полностью размер, который использовался для обновления моей панели прогресса на сервере. Не могли бы вы помочь мне решить мою путаницу? – Leo

+1

Поток QData хранит размер строки, поэтому вам тоже не нужно ее писать. В этом шаблоне размер попрошайки необходим только для проверки того, что полный контент уже доступен, поскольку «QDataStream» и «QTcpSocket» не работают, если не все данные потока доступны (сокеты передают данные в кусках, которые не должны отражать процесс отправки). В любом случае 'QDataStream' сохраняет размер элемента, если это необходимо. –

+0

О, я просто понял ваш смысл. Благодаря! – Leo

0

info.filename()writes out its own length

, если вы не хотите, чтобы после этого вы можете сделать

QFileInfo info(file_to_send.fileName()); 
QByteArray head; 
QDataStream out(&head, QIODevice::WriteOnly); 
out.setVersion(QDataStream::Qt_5_0); 
QByteArray filename = info.fileName().toLatin1(); 
out << qint32(file_to_send.size() + filename .length() + sizeof(qint32)*2); 
    << qint32(filename .length()) 
out.writeRawData(fileName.constData(), filename.length()); 
tcpClient.write(head); 

используя writeRawData, который обходит любые встроенные кодировки

+0

Отлично, очень полезно! Должен ли я использовать один и тот же класс на клиенте и на сервере? Я использовал QString в клиенте, и я обнаружил, что использование QByteArray (в >> QByteArray) на сервере не работает. – Leo

+0

Да, вы правы! 4 + 4 + 4 (длина QString) + 2 * (QString, UTF-16) = 4 + 4 + 4 + 2 * strlen ("Screenshot.png") = 40 (размер заголовка) – Leo

Смежные вопросы