0

i need the checksum of a file and found this, which works perfectly fine. Now i want to change this function to take a pointer to a QIODevice that has been opened before with the following lines:

if (!file.open(QFile::ReadOnly | QFile::Text))
{
    ...
}

This is passed to read (reader.read(&file);) as device:

bool XmlReader::read(QIODevice* device)
{
    QByteArray b = fileChecksum(device);
    ...
}

This is my implementation of fileChecksum. It returns a checksum, but i am caught in a loop forever and i am getting an xml parse error. What am i doing wrong here?

QByteArray XmlReader::fileChecksum(QIODevice* device)
{
    if (device->isOpen())
    {
        QCryptographicHash hash(QCryptographicHash::Sha256);
        if (hash.addData(device)) {
            return hash.result();
        }

    }
    return QByteArray();
}

EDIT

right after QByteArray b = fileChecksum(device); i do:

qDebug() << "Checksum: " << b.toHex();

whick keeps printing and printing and printing...

The parse error is: premature end of document which is rubbish.

Hope this helps.

Community
  • 1
  • 1
tobilocker
  • 891
  • 8
  • 27
  • Could you please post exact error text? Also it is not very clear in what loop you are caught, could you please clarify? – demonplus Nov 14 '16 at 08:05
  • @tobilocker the error is somewhere that in the parts of your code that is not included in this question. You should be aware that the `addData` function most likely reads the whole file and then doesn't "rewind" the cursor, so you might want to do `auto pos = device->pos();QByteArray b = fileChecksum(device);device->seek(pos);` – PeterT Nov 14 '16 at 10:05
  • @PeterT That did it! Perfect! If you just add those lines as an answer i can accept it. – tobilocker Nov 16 '16 at 08:48

1 Answers1

1

Since the lines of code that eventually caused the error are not in view I can only speculate about what happened.

The function fileChecksum called hash.addData(device) which read the QIODevice until the end and kept the cursor position there.

Most likely you tried to read from the QIODevice afterwards which would explain the premature end of documen message.

As a fast workaround you can just try to reset the position afterwards with

auto pos = device->pos();
QByteArray b = fileChecksum(device);
device->seek(pos);

But you should only read the data once if you can (to support non random-access QIODevices too). For example you can store the result in a QBuffer and use that as a QIODevice. Like this:

bool XmlReader::read(QIODevice* device)
{
    QByteArray contents = device->readAll();
    QBuffer buffer(&contents);
    device = &buffer;//you can also just use &buffer from here on out instead of overwriting the pointer
    QByteArray b = fileChecksum(device);
    device->reset();
    /* ... further reads from device here */
}
PeterT
  • 7,981
  • 1
  • 26
  • 34
  • Guess confirmed! Thanks. – tobilocker Nov 16 '16 at 18:48
  • You did not test this right? The above won't compile. There are several errors in your suggested solution with the `QBuffer`. `QByteArray contents = device.readAll();` obviously doesn't work since device is a pointer. `QBuffer` constructor takes a pointer to a `QByteArray` so it must be `QBuffer buffer(&contents)`. Also this results in the same parser error `premature end of document`. – tobilocker Nov 17 '16 at 08:01
  • @tobilocker yep, didn't try to compile. Also, when the error still appears you probably read from `device` outside of the `XmlReader::read` function which I did not assume. I guess just make sure that the `QIODevice` that you pass in is a random access device and then then you can just rely on the initial workaround. – PeterT Nov 17 '16 at 08:13