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