【问题标题】:Writing/reading std::complex values in binary file在二进制文件中写入/读取 std::complex 值
【发布时间】:2017-02-14 20:33:41
【问题描述】:

我假装将std::complex<float>std::vector 存储在二进制文件中,然后再将该数据加载到std::vector 中。我在 SO 中检查了类似的问题,并提出了以下代码:

#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

我错过了什么?

编辑: 在 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;
}

我在第一次调用 write 函数时得到了一个 SIGSEGV。

另外,我不明白我为什么要写作,但我必须阅读。

【问题讨论】:

  • 您可能缺少std::ios::outstd::ios::in 标志。您是否检查过您的文件是否实际创建并包含数据?
  • 您不能将二进制写入与格式化读取混合使用。如果你write你需要的数据read数据。为了更容易,您应该首先write 向量的大小,这样您就可以read 它并分配存储空间,以便您可以read 在数据中。
  • 不要将srandstd::default_random_engine 混为一谈 :)
  • @NathanOliver 到底哪里出了问题?我看到类似的例子是这样完成的......我既用二进制写又读,所以我不明白出了什么问题
  • 您没有阅读二进制文件。 complex_vector auxBuffer{std::istream_iterator&lt;complex&lt;float&gt;&gt;(input), std::istream_iterator&lt;complex&lt;float&gt;&gt;()}; 不会进行二进制读取,即使文件以二进制模式打开。

标签: c++ binary


【解决方案1】:

您不能将二进制写入与您现在正在做的格式化读取混合使用。即使文件以二进制模式打开

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

调用运算符>>ofcomplex>and notreadwhich is what you should use if you write the data withwrite`。

您有两种方法可以解决此问题。您可以进行格式化写入,而不是像二进制一样

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());

我个人喜欢第一个选项,因为它看起来更干净,但如果这对性能敏感,那么二进制模式通常更快。

【讨论】:

  • 由于输出文件的大小太重,我需要它是二进制的。第二个选项不编译:从‘const char*’到‘std::basic_istream::char_type* {aka char*}’的无效转换[-fpermissive](在第一次读取调用时)。另外,我不明白为什么它不能像我尝试的那样工作,就像这里指定的那样:stackoverflow.com/a/5420568/808091
  • @RomanRdgz 我的代码有错误。 write 调用需要使用reinterpret_cast&lt;char*&gt; 而不是reinterpret_cast&lt;const char*&gt;。代码已更新。
  • 似乎仍然不起作用:cpp.sh/7fhuz 另外,在我的本地代码中,我在第一次写入时就获得了 SIGSEGV
  • @RomanRdgz 它不适用于 C++ Shell,因为您无法创建文件。我确实发现了另一个错误,sizeof(std::complex&lt;float&gt;) * buffer-&gt;size() 应该是sizeof(std::complex&lt;float&gt;) * auxBuffer-&gt;size()。所以rawFile.write(reinterpret_cast&lt;const char*&gt;(buffer-&gt;size()), sizeof(buffer-&gt;size())); 给你一个 sigsev?
  • 没错,我正在那里得到一个 SIGSEGV。以前我声明 std::ofstream rawFile("aux.bin", std::ios::binary);并且文件确实被创建了。下一行是用 sigsegv 写的,不知道为什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多