QT C++从文件中读取大量数据并将其存储在内存中的好方法是什么?

3phpmpom  于 2023-02-06  发布在  其他
关注(0)|答案(1)|浏览(444)

我有音频数据,我不知道什么是最好的方式来存储它作为矩阵。我有4个大文件的录音从声学传感器,每个文件有4个通道的数据交错。我正在使用Qt C++做一些处理这些数据。我已经做了这种方法使用qvector的qvector来存储数据。

QVector<QVector<int>> buffer(16) // 4 * 4 : numberOfChannels * numberOfFiles

for(int i = 0 ; i < 4 ; i++){ 
    QFile file(fileList[i]);    // fileList is QList of QStrings contains 4 files path
    if(file.open(QIODevice::ReadOnly)){
        int k = 0;
        while(!file.atEnd()){
            QByteArray sample = file.read(depth/8); // depth here is 24
            int integerSample = convertByteArrayToIntFunction(sample);
            buffer[4 * i + (K%4)].append(integerSample);    
            k++;

        }
    }
}

要在末尾具有如下所示的16列矩阵(f:文件,c:通道):
f1c0|f1c1|二聚体|三氟甲烷|氟二羧酸|F2C1|...|二氟甲烷|三氟甲烷
但是这种方法对于几GB的大文件来说需要很长时间。我想知道是否有另一种有效的方法来完成这项任务并节省大量时间。正如我发现的那样,我可以将阅读从文件划分为块,但仍然不清楚。提前感谢。

xmjla07d

xmjla07d1#

代码中有两个明显的反模式。
第一个问题是不预先调整QVector的大小。这意味着对append的调用经常会注意到向量的存储空间已满,这会触发为更大的向量分配内存,然后在append完成之前复制向量的内容。因此,您可以使用QVector::reserve提前分配正确的数量并抑制此行为:

const int bps = depth / 8;
QFile file (fileList[i]);
auto numSamples = file.size() / bps / 4; // "depth" bits per sample and 4 channels
for (int j = 0; j < 4; j++) {
  buffer[4 * i + j].reserve(numSamples);
}

第二,对每个样本都调用file.read(),这意味着要重复地付出检索数据(尽管缓冲会稍微减轻一点)和分配QByteArray的代价,而是一次读取文件的一大块,然后循环:

while (!file.atEnd()) {
  QByteArray samples = file.read(1'000'000 * 4 * bps); // read up to a million samples at once
  for (int k = 0; k * bps < samples.size(); k++) {
    QByteArray sample = samples.mid(k * bps, bps);
    buffer[4 * i + (k % 4)].append(convertByteArrayToIntFunction(sample));
  }
}

您可以尝试一下1'000'000的数字,看看是否有一个更优的数字,通过将convertByteArrayToIntFunction传递给const char *,您可能会获得几个百分点的性能提升,但可读性可能更好。

相关问题