Прочитать и отправить файл через QDataStream и QTcpSocket - PullRequest
0 голосов
/ 05 октября 2011

Моя проблема в том, что содержимое переменной всегда пусто.Вот мой код:

QFile file("/home/qt/Client/file.txt");
if(file.open(QIODevice::ReadOnly)){
    qDebug("File opened");
}

QDataStream fileData(&file);

QByteArray content;
QDataStream out(&content, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);  

out << static_cast<quint16>(0) << "file" << "/home/qt/Client/file.txt" << fileData;

out.device()->seek(0);
out << static_cast<quint16>(content.size());

qDebug() << content.constData();

tcpSocket->write(content);

Вывод:

File opened

содержимое всегда пусто

спасибо за вашу помощь

1 Ответ

4 голосов
/ 05 октября 2011

content не является пустым, но если вы интерпретируете его как строку с 0-символом в стиле C, она будет выглядеть пустой.

Когда вы пишете:

out.device()->seek(0);
out << static_cast<quint16>(content.size());

Это установит первые два байта content в content.size() в формате с прямым порядком байтов (это значение по умолчанию). Поэтому, если content.size() меньше 255, первый байт content.constData() будет равен 0 ('\0'). Любая попытка напечатать constData() с помощью функции, которая ожидает строку в стиле C, ничего не даст, поскольку ваша «строка» начинается с маркера «конец строки».

Если вы хотите увидеть полное содержимое content, вы должны распечатать все его символы отдельно и использовать что-то вроде hexdump для просмотра необработанных данных.

Вот что я получу, если сделаю это вместо qDebug() << content.constData();:

for (int i=0; i<content.size(); i++) {
    std::cout << content.constData()[i];
}

Вывод при запуске (файл содержит всего 20 'a' символов):

 $ ./qt | hexdump -C
00000000  00 40 00 00 00 05 66 69  6c 65 00 00 00 00 19 2f  |.@....file...../|
00000010  68 6f 6d 65 2f 71 74 2f  43 6c 69 65 6e 74 2f 66  |home/qt/Client/f|
00000020  69 6c 65 2e 74 78 74 00  00 00 00 14 61 61 61 61  |ile.txt.....aaaa|
00000030  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
00000040

Если бы я использовал:

std::cout << content.constData();

Не было бы выхода из-за того самого первого 0 символа.

Если ваши данные длиннее, а размер content больше 255, первый символ больше не будет 0, но вы напечатаете два символа мусора и ничего больше, потому что Qt сериализует QString (и большинство других типов), сначала записывая его длину (32-битная здесь), затем его содержимое. Поскольку он находится в значении с прямым порядком байтов, первый байт имеет очень высокий шанс быть равным 0.

Аннотированный вывод:

00000000  00 40 00 00 00 05 66 69  6c 65 00 00 00 00 19 2f  |.@....file...../|
          <u16> < str len > <  str data   > < str len > <
00000010  68 6f 6d 65 2f 71 74 2f  43 6c 69 65 6e 74 2f 66  |home/qt/Client/f|
                               str data...
00000020  69 6c 65 2e 74 78 74 00  00 00 00 14 61 61 61 61  |ile.txt.....aaaa|
            str data            >  <data len > < 
00000030  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
                    data                                 >
...