2017-02-13 6 views
1

Я притворяюсь, что в двоичном файле записывается std::vector из std::complex<float>, а затем снова загружать эти данные в std :: vector. Я проверил подобные вопросы в SO и придумал следующий код:Запись/чтение std :: complex values ​​в двоичном файле

#include <complex> 
#include <iostream> 
#include <memory> 
#include <fstream> 
#include <iterator> 
#include <random> 
#include <vector> 

using namespace std; 
typedef vector<complex<float>> complex_vector; 


float get_random(){ 
    static std::default_random_engine e; 
    static std::uniform_real_distribution<> dis(-10, 10); 
    return dis(e); 
} 

int main(){ 
    // Random number generator 
    srand(static_cast<unsigned> (time(0))); 

    // Create a vector with 25 random complex<float> values 
    std::shared_ptr<vector<complex<float>>> buffer = std::make_shared<vector<complex<float>>>(); 
    for(unsigned int i=0; i<25; i++){ 
     buffer->push_back(complex<float>(get_random(), get_random())); 
    } 

    // Write those values into a binary file 
    std::string binFileName = "aux.bin"; 
    std::ofstream rawFile(binFileName, std::ios::binary); 
    for(unsigned int i=0; i<buffer->size(); i++){ 
     rawFile.write(reinterpret_cast<const char*>(&buffer->at(i)), sizeof(complex<float>)); 
    } 
    rawFile.close(); 

    // Load the binary file into the buffer 
    std::ifstream input(binFileName, std::ios::binary); 
    complex_vector auxBuffer{std::istream_iterator<complex<float>>(input), std::istream_iterator<complex<float>>()}; 
    unsigned int samplesRead = auxBuffer.size(); 
    std::cout << samplesRead; 

    return 0; 
} 

Выход:

0 

Что мне не хватает?

EDIT: После ответа NathanOliver, это то, как мой код выглядит сейчас:

#include <complex> 
#include <iostream> 
#include <memory> 
#include <fstream> 
#include <iterator> 
#include <random> 
#include <vector> 

using namespace std; 
typedef vector<complex<float>> complex_vector; 


float get_random(){ 
    static std::default_random_engine e; 
    static std::uniform_real_distribution<> dis(-10, 10); 
    return dis(e); 
} 

int main(){ 
    // Random number generator 
    srand(static_cast<unsigned> (time(0))); 

    // Create a vector with 25 random complex<float> values 
    std::shared_ptr<complex_vector> buffer = std::make_shared<complex_vector>(); 
    for(unsigned int i=0; i<25; i++){ 
     buffer->push_back(complex<float>(get_random(), get_random())); 
    } 

    // Write those values into a binary file 
    std::string binFileName = "aux.bin"; 
    std::ofstream rawFile(binFileName, std::ios::binary); 
    rawFile.write(reinterpret_cast<const char*>(buffer->size()), sizeof(buffer->size())); 
    rawFile.write(reinterpret_cast<const char*>(buffer->data()), sizeof(std::complex<float>) * buffer->size()); 
    rawFile.close(); 

    // Load the binary file into the buffer 
    std::ifstream input(binFileName, std::ios::binary); 
    complex_vector::size_type nSamples; 
    input.read(reinterpret_cast<char*>(nSamples), sizeof(complex_vector::size_type)); 
    std::cout << nSamples; 
    complex_vector *destination = new complex_vector(25); 
    input.read(reinterpret_cast<char*>(destination->data()), sizeof(std::complex<float>) * nSamples); 

    return 0; 
} 

Я получаю SIGSEGV в первом вызове написать функцию.

Кроме того, я не понимаю, почему я пишу, но я должен прочитать.

+0

Возможно, вам не хватает флагов 'std :: ios :: out' и' std :: ios :: in'. Вы проверяли, действительно ли ваш файл создан и содержит данные? – paddy

+2

Вы не можете смешивать двоичные записи с форматированными чтениями. Если вы «запишите» данные, которые вам нужно «прочитать» данные. Чтобы сделать это проще, вы должны «написать» размер вектора первым таким образом, чтобы вы могли «прочитать» его и выделить хранилище, чтобы вы могли «читать» в данных. – NathanOliver

+0

И не смешивайте 'srand' с' std :: default_random_engine' :) –

ответ

1

Вы не можете смешивать двоичные записи с форматированными считаниями, которые вы сейчас делаете. Даже если файл открыт в двоичном режиме

complex_vector auxBuffer{std::istream_iterator<complex<float>>(input), std::istream_iterator<complex<float>>()}; 

называет оператор >>of комплекс>and not чтения which is what you should use if you write the data with write`.

У вас есть два способа исправить это. Вы можете делать форматированные записи вместо двоичных, например

for (const auto& e : *buffer) 
    rawFile << e << "\n"; // or space or any other white space delimiter 

И тогда вы прочтете его точно так же, как у вас есть.

Другой вариант заключается в write размер вектора, а содержимое вектора, а затем read те и обратно, как

// write the size of the vector 
rawFile.write(reinterpret_cast<const char*>(&buffer->size()), sizeof(buffer->size())); 
// write the whole contents of the vector in one go 
rawFile.write(reinterpret_cast<const char*>(buffer->data()), sizeof(std::complex<float>) * buffer->size()); 

// and then to read it back in we get the size 
complex_vector::size_type size; 
input.read(reinterpret_cast<char*>(&size), sizeof(size)); 
// construct a vector of that size 
complex_vector auxBuffer(size); 
// and then read the data back into the vector 
input.read(reinterpret_cast<char*>(auxBuffer.data()), sizeof(std::complex<float>) * auxBuffer->size()); 

Лично мне нравится первый вариант, как это выглядит намного чище, но если это чувствительность к производительности, тогда двоичный режим, как правило, быстрее.

+0

Мне нужно, чтобы он был двоичным из-за размера выходных файлов, который становится слишком тяжелым. Второй параметр не компилируется: неверное преобразование из 'const char *' в 'std :: basic_istream :: char_type * {aka char *}' [-fpermissive] (при первом запросе на чтение). Кроме того, я не понимаю, почему он не работает, как я пытался, так же, как указано здесь: http://stackoverflow.com/a/5420568/808091 –

+0

@RomanRdgz У меня была ошибка в коде. Призывы к записи необходимо использовать 'reinterpret_cast ', а не 'reinterpret_cast '. Код обновлен. – NathanOliver

+0

Похоже, что не работает: http://cpp.sh/7fhuz Плюс, в моем локальном коде, я получаю SIGSEGV при первой записи –

Смежные вопросы