C ++ /快速随机访问在大文件中跳过

时间:2016-12-21 22:33:24

标签: c++ file random-access

我有大文件,包含少量大数据集。每个数据集都包含一个名称和数据集大小(以字节为单位),允许跳过它并转到下一个数据集。

我想非常快速地建立数据集名称的索引。文件示例大约21MB,包含88个数据集。使用std::ifstreamseekg()在数据集之间跳过快速读取88个名称需要大约1300毫秒,我想减少。

事实上,我在21MB文件中的给定位置读取了大约30个字节的88个块,需要1300ms。

有没有办法改进这个,还是操作系统和文件系统限制?我在 Windows 7 64位下运行测试。

我知道在文件开头有一个完整的索引会更好,但文件格式没有这个,我们无法改变它。

3 个答案:

答案 0 :(得分:5)

您可以使用内存映射文件界面(我推荐boost's implementation.

这会将文件打开到应用程序的虚拟页面中,以便更快地查找时间,而无需返回磁盘。

答案 1 :(得分:2)

您可以扫描文件并使用单独的文件中的密钥和索引创建自己的标头。根据您的使用情况,您可以在程序启动时和文件每次更改时执行一次。 在访问大数据之前,在较小的文件中查找会为您提供所需的索引。

答案 2 :(得分:0)

您可以使用多线程执行缓冲区排队过程。您可以创建一个存储各种数据量的自定义结构。

你说:

  

每个数据集都包含一个名称和数据集大小(以字节为单位),允许跳过它并转到下一个数据集。

因此,一次又一次地打开和关闭文件很慢,您可以一次性读取文件并将其存储到完整的缓冲区对象中,然后解析或将其存储到批处理中。这还取决于您是以文本还是二进制模式阅读解析文件的容易程度。我将通过填充多个批次来演示后者,同时从文件中读取缓冲大小的数据量。

伪代码

struct Batch {
    std::string name; // Name of Dataset
    unsigned size;    // Size of Dataset
    unsigned indexOffset;  // Index to next read location
    bool empty = true;     // Flag to tell if this batch is full or empty
    std::vector<DataType> dataset; // Container of Data
}; 

std::vector<Batch> finishedBatches;

// This doesn't matter on the size of the data set; this is just a buffer size on how much memory to digest in reading the file
const unsigned bufferSize = "Set to Your Preference" 1MB - 4MB etc.

void loadDataFromFile( const std::string& filename, unsigned bufferSize, std::vector<Batch>& batches ) {

    // Set ifstream's buffer size 

    // OpenFile For Reading and read in and upto buffer size

    // Spawn different thread to populate the Batches and while that batch is loading 
    // in data read in that much buffer data again. You will need to have a couple local 
    // stack batches to work with. So if a batch is complete and you reached the next index 
    // location from the file you can fill another batch.

    // When a single batch is complete push it into the vector to store that batch.
    // Change its flag and clear its vector and you can then use that empty batch again.

    // Continue this until you reached end of file.           

}

这将是一个双线程系统。用于打开和读取文件以及从文件中搜索的主线程,其中工作线程填充批次并将批次推入容器并交换以使用下一批次。