Как записать 2D вектор в двоичный файл? - PullRequest
1 голос
/ 19 ноября 2011

все!У меня есть 2D-вектор, заполненный без знака.Теперь я хочу сохранить его содержимое в двоичном файле:

std::vector<std::vector<unsigned char> > v2D(1920, std::vector<unsigned char>(1080));

// Populate the 2D vector here
.....

FILE* fpOut;

// Open for write
if ( (err  = fopen_s( &fpOut, "e:\\test.dat", "wb")) !=0 )
{   
   return;
}

// Write the composite file
size_t nCount = 1920 * 1080 * sizeof(unsigned char);
int nWritten = fwrite((char *)&v2D[0][0], sizeof(unsigned char), nCount, fpOut);

// Close file
fclose(fpOut);

Но когда я читаю test.dat, заполняю новый 2D-вектор и сравниваю его записи со старыми.Я считаю, что письменное содержание не совпадает с оригиналом.Зачем?Что не так с моим заявлением?Подскажите, пожалуйста, как правильно записать 2D-вектор в двоичный файл?Большое спасибо!

    #define LON_DATA_ROWS 1920
    #define LON_DATA_COLS 1080

    std::vector<std::vector<float> > m_fLon2DArray(LON_DATA_ROWS, std::vector<float>(LON_DATA_COLS));

    std::ifstream InputFile;

    int nSizeOfLonData = TOTAL_LON_ELEMENTS * sizeof(float);

    std::vector<char> vLonDataBuffer(nSizeOfLonData);

    // Open the file
    InputFile.open(m_sNorminalLonLatFile.c_str(), ios::binary);

    // Unable to open file pszDataFile for reading
    if ( InputFile.fail() )
       return false;

    // Read longitude data buffer
    InputFile.read(&vLonDataBuffer[0], nSizeOfLonData);

    // Close the file object
    InputFile.close();

    // Populate the longitude 2D vector
    for (unsigned i = 0; i < LON_DATA_ROWS; i++) 
    {   
        memcpy(&m_fLon2DArray[i][0], &vLonDataBuffer[(i * LON_DATA_COLS) * sizeof(float)], LON_DATA_COLS * sizeof(float));
    }

    // Some operation put here

    // Write the results to a binary file

Ответы [ 3 ]

4 голосов
/ 19 ноября 2011

Это неправильно. Данные, содержащиеся в v2D, НЕ находятся в непрерывной памяти. Тем не менее, каждый элемент v2D (который является вектором) находится в непрерывной памяти. То есть данные, содержащиеся в v2D[i], находятся в непрерывной памяти.

Итак, вы должны сделать это:

int nWritten = 0;
for(size_t i = 0; i < v2D.size(); i++ )
{
   if ( v2D[i].size() > 0 )
     nWritten += fwrite(&v2D[i][0], sizeof(unsigned char), v2D[i].size(), fpOut);
}

Или вы можете использовать C ++ IOStream как:

std::ofstream file("E:\\test.data", std::ofstream::binary);
for(size_t i = 0; i < v2D.size(); i++ )
{
    if ( v2D[i].size() > 0 )
    {
       const char* buffer = static_cast<const char*>(&v2D[i][0]);
       file.write(buffer, v2D[i].size());
    }
}
3 голосов
/ 19 ноября 2011

Вектор векторов в памяти выглядит не так:

|---------|---------|---------|---------|...   (where "-" is one element)
     0         1         2         3        

А вот так:

|->0x48267a70|->0x894753b2|->0xb8cc92f0|->0x22d8cc71|...

(каждый вектор имеет указатель на свои внутренние данные, который будетперераспределить, когда рост превысит объем уже выделенной памяти).

Что вы сделали, вы взяли адрес внутреннего буфера первого вектора и переиндексировали его после исчерпания его элементов.Это неопределенное поведение, и поэтому в вашем файле есть ненужная память (но у вас была одинаковая вероятность сбоя программы).

Вы можете записать сохраненные векторы один за другим в файл, выполняя итерации.В более идиоматическом стиле C ++:

std::ofstream outfile("e:\\test.dat", std::ios::binary | std::ios::out);
if (!outfile.is_open()) ... // handle error

for (std::vector<std::vector<unsigned char> >::iterator it = v2D.begin();
     it != v2D.end();
     ++it)
{
    outfile.write(&it->front(), it->size() * sizeof(unsigned char));
}

Или в C ++ 11 вышеприведенное будет выглядеть следующим образом:

for (auto& it : v2D) 
{
    outfile.write(&it.front(), it.size() * sizeof(unsigned char)); 
}

В обоих случаях ios_base::failure исключения должны обрабатываться.

1 голос
/ 19 ноября 2011

Существует два основных способа создания двумерной матрицы: путем определения области памяти * m или с помощью списка из n указателей на m векторов.у вас есть вариант последнего.

вы делаете запись списка векторов данных в файл ... Ваши данные не являются непрерывными , поэтому вы пишетеДанные экземпляра класса "vector" в файл.

Вы можете записать каждый из субвекторов один за другим или использовать один вектор 1920 * 1080 и записать в файл, как вы это сделали.

...