如何优化这个Qt代码(QByteArray转换)?

时间:2014-05-24 05:18:39

标签: qt optimization

我需要对二进制数据执行一些正则表达式操作。我写了一个函数来转换六进制字符串表示中的QByteArray数据。每个字节前缀为'x'用于解析目的。

如何优化此代码?

QByteArray data;
QByteArray newData;

for (int i = 0; i < data.size(); i++) {

    QString hex;
    hex.setNum(data[i], 16);

    if (data[i] < 10) {

        hex.prepend("x0");

    } else {

        hex.prepend("x");
    }

    newData.append(hex.toLatin1());
}

1 个答案:

答案 0 :(得分:1)

您发布的代码中有两个错误我已更正。

1)假设你总是想要两个十六进制数字,你想检查这个值是否小于16,而不是10。

2)QString::setNum没有char的重载,因此该值被提升为更大的类型。对于128这样的值,在已签名的字符中为负数,由于符号扩展,您将获得x0ffffffffffffff80

函数foo1是修复了错误的原始代码,foo2是一个更优的版本,可以避免创建临时QString,因为转换为unicode并且返回isn&#39 ; t free,并在字符串前加上值需要额外的复制。

我使用QElapsedTimer,因为在我测试它的Windows上使用高分辨率PerformanceCounter时钟。如果您在另一个平台上,它可能不太准确。您可以在文档中看到它可能使用的不同类型的时钟。

如果您希望打印转换的字符串以验证它们是否相同,请将display_converted_string设置为true。

#include <QString>
#include <QByteArray>
#include <QElapsedTimer>
#include <iostream>

QByteArray foo1(QByteArray data)
{
    QByteArray newData;
    for (int i = 0; i < data.size(); i++) {
        unsigned char c = data[i];
        QString hex;
        hex.setNum(c, 16);
        if (c < 16) {
            hex.prepend("x0");
        } else {
            hex.prepend("x");
        }
        newData.append(hex.toLatin1());
    }
    return newData;
}

QByteArray foo2(QByteArray data)
{
    static const char digits[] = {'0','1','2','3','4','5','6','7',
                                  '8','9','a','b','c','d','e','f'};
    QByteArray newData;
    newData.reserve(data.size() * 3);
    for (int i = 0; i < data.size(); i++)
    {
        unsigned char c = data[i];
        newData.append('x');
        newData.append(digits[(c >> 4) & 0x0f]);
        newData.append(digits[c & 0x0f]);
   }
   return newData;
}

int main()
{
    const int iterations = 10000;
    const bool display_converted_string = false;

    QElapsedTimer t;
    std::cout << "Using clock type " << t.clockType() << ".\n";

    QByteArray data(256, 0);
    QByteArray newData;
    qint64 elapsed1 = 0, elapsed2 = 0;
    //Set the values in data to 0-255 to make sure all values are converted properly.
    for(int i = 0; i < data.size(); ++i)
    {
        data[i] = i;
    }

    t.start();
    for(int i = 0; i < iterations; ++i)
    {
        newData = foo1(data);
    }
    elapsed1 = t.nsecsElapsed();
    std::cout << "foo1 elapsed time = " << elapsed1 << "\n";
    if(display_converted_string)
    {
        std::cout << "newData = " << newData.data() << "\n";
    }

    t.restart();
    for(int i = 0; i < iterations; ++i)
    {
        newData = foo2(data);
    }
    elapsed2 = t.nsecsElapsed();
    std::cout << "foo2 elapsed time = " << elapsed2 << "\n";
    if(display_converted_string)
    {
        std::cout << "newData = " << newData.data() << "\n";
    }
    return 0;
}