C++ Загрузите бинарный файл в память и получите объекты

У меня есть двоичный файл, в котором я сохраняю следующие переменные миллионы раз:

  • x-размерный вектор поплавков
  • два целых числа без знака

В настоящее время я использую ifstream для открытия и чтения файла, но мне было интересно, смогу ли я ускорить время выполнения, загрузив весь файл в память и сократив количество операций ввода-вывода.

Как я могу загрузить файл в память и затем преобразовать его в переменные, которые я хочу? С ifstream это делается легко, но я не знаю, как его буферизовать и затем извлекать данные.

Это код, который я использую для сохранения данных:

osfile.write(reinterpret_cast<const char*> (&sz), sizeof(int));// Size of vector
osfile.write(reinterpret_cast<const char*> (&vec[0]), sz*sizeof(float));
osfile.write(reinterpret_cast<const char*> (&a), sizeof(unsigned int));
osfile.write(reinterpret_cast<const char*> (&b), sizeof(unsigned int));

2 ответа

Вот подход, который я бы предложил. Сначала прочитайте весь файл в буфер:

std::ifstream binFile("your_binary_file", std::ifstream::binary);
if(binFile) {
    // get length of file
    binFile.seekg(0, binFile.end);
    size_t length = static_cast<size_t>(binFile.tellg());
    binFile.seekg(0, binFile.beg);

    // read whole contents of the file to a buffer at once
    char *buffer = new char[length];
    binFile.read(buffer, length);
    binFile.close();

    ...

Затем извлеките вектор и целые числа, используя этот подход:

    size_t offset = 0;
    int vectorSize = *reinterpret_cast<int*>(buffer);
    offset += sizeof(int);

    float *vectorData = reinterpret_cast<float*>(buffer + offset);
    std::vector<float> floats(vectorSize);
    std::copy(vectorData, vectorData + vectorSize, floats.begin());
    offset += sizeof(float) * vectorSize;

    int i1 = *reinterpret_cast<int*>(buffer + offset);
    offset += sizeof(int);
    int i2 = *reinterpret_cast<int*>(buffer + offset);

Наконец, когда все данные прочитаны, не забудьте удалить память, выделенную для буфера:

    delete[] buffer;
}

Я предполагаю, что чего-то не хватает в вашей процедуре записи, потому что размер вектора отсутствует в вашем потоке записи...

size_t size = vec.size();
osfile.write(reinterpret_cast<const char*> (&size), sizeof(size_t));
osfile.write(reinterpret_cast<const char*> (&vec[0]), vec.size()*sizeof(float));

osfile.write(reinterpret_cast<const char*> (&i), sizeof(unsigned int));
osfile.write(reinterpret_cast<const char*> (&i), sizeof(unsigned int));

Затем вы можете загрузить глобальный файловый буфер в память: прочитать весь файл ASCII в C++ std::string

Затем передайте загруженный буфер istringstream iss; объект

Затем прочитайте ваш поток так же, как вы его написали (потоковый подход):

float tmp;
size_t size_of_vector;
// read size of vector
iss >> size_of_vector;
// allocate once
vector<float> vec(size_of_vector);
// read content
while(size_of_vector--)
{
    iss >> tmp;
    vec.push_back(tmp);
}
// at the end, read your pair of int
unsigned int i1,i2;
iss >> i1;
iss >> i2;

РЕДАКТИРОВАТЬ: Вы все еще должны позаботиться о двоичных и символьных соображений при открытии / чтении потоков...

Другие вопросы по тегам