C++ 如何在C+中读取复数二进制文件+;

C++ 如何在C+中读取复数二进制文件+;,c++,matlab,C++,Matlab,我有一个320Mb的二进制文件(data.dat),包含32e7行十六进制数: 1312cf60 d9 ff e0 ff 05 00 f0 ff 22 00 2f 00 fe ff 33 00 |........"./...3.| 1312cf70 00 00 00 00 f4 ff 1d 00 3d 00 6d 00 53 00 db ff |........=.m.S...| 1312cf80 b7 ff b0 ff 1e 00 0c 00 67 00 d1 ff be ff f8 ff |

我有一个320Mb的二进制文件(data.dat),包含32e7行十六进制数:

1312cf60 d9 ff e0 ff 05 00 f0 ff 22 00 2f 00 fe ff 33 00 |........"./...3.|
1312cf70 00 00 00 00 f4 ff 1d 00 3d 00 6d 00 53 00 db ff |........=.m.S...|
1312cf80 b7 ff b0 ff 1e 00 0c 00 67 00 d1 ff be ff f8 ff |........g.......|
1312cf90 0b 00 6b 00 38 00 f3 ff cf ff cb ff e4 ff 4b 00 |..k.8.........K.|
....
nsamps = (256*1024);
for i = 1:305
     nstart = 1 + (i - 1) * nsamps ;
     fid = fopen('data.dat');
     fseek(fid,4 * nstart ,'bof');
     y = fread(fid,[2,nsamps],'short');
     fclose(fid);
     x = complex(y(1,:),y(2,:));
原来的数字是:

(16,-144)
(-80,-64)
(-80,16)
(16,48)
(96,95)
(111,-32)
(64,-96)
(64,-16)
(31,-48)
(-96,-48)
(-32,79)
(16,48)
(-80,80)
(-48,128)
...
我有一个matlab代码,可以将它们作为实数读取,并将它们转换为复数:

1312cf60 d9 ff e0 ff 05 00 f0 ff 22 00 2f 00 fe ff 33 00 |........"./...3.|
1312cf70 00 00 00 00 f4 ff 1d 00 3d 00 6d 00 53 00 db ff |........=.m.S...|
1312cf80 b7 ff b0 ff 1e 00 0c 00 67 00 d1 ff be ff f8 ff |........g.......|
1312cf90 0b 00 6b 00 38 00 f3 ff cf ff cb ff e4 ff 4b 00 |..k.8.........K.|
....
nsamps = (256*1024);
for i = 1:305
     nstart = 1 + (i - 1) * nsamps ;
     fid = fopen('data.dat');
     fseek(fid,4 * nstart ,'bof');
     y = fread(fid,[2,nsamps],'short');
     fclose(fid);
     x = complex(y(1,:),y(2,:));

我使用C++,并尝试将数据作为<代码>向量 >:

std::ifstream-in('data.dat',std::ios_base::in | std::ios_base::binary);
fseek(填充1,4*nstart,搜索集);
矢量sx;
in.read(reinterpret_cast(&sx),sizeof(int));
用C++获取复杂数据非常混淆。谁能帮我一个忙吗?

我将尝试以代码中的问题为例来解释一些要点

让我们从代码的末尾开始。您尝试读取一个存储为四字节单精度的数字,但使用
sizeof(int)
作为大小参数。虽然在使用现代编译器的现代x86平台上,
sizeof(int)
往往等于
sizeof(float)
,但这并不能保证
sizeof(int)
依赖于编译器,因此请改用
sizeof(float)

<>在MATLAB代码中,你读了代码> 2×nSAMPs/COD>数字,而C++代码中只读取四字节(一个数)。类似于
sizeof(float)*2*nsamps
的代码更接近matlab代码

接下来,
std::complex
是一个复杂的类,它(通常)可以有任何实现定义的内部表示。但幸运的是,我们读到了

对于类型为
complex
的任何对象
z
reinterpret\u cast(z)[0]
z
的真实部分,
reinterpret_cast(z)[1]
z
的虚部

对于指向名为
p
复杂
数组元素的任何指针,以及 任何有效的数组索引
i
reinterpret\u cast(p)[2*i]
都是实部 复数的
p[i]
重新解释(p)[2*i+1]
是 复数的虚部
p[i]

因此,我们可以将一个
std::complex
强制转换为char类型,并在那里读取二进制数据。但是
std::vector
是一个类模板,它的实现定义了内部表示!这意味着,我们不能仅仅
重新解释\u cast(&sx)
并将二进制数据写入指针,因为指针指向向量对象的开头,而向量对象不太可能是向量数据的开头。获取数据开头的现代C++方式是调用<代码> SX.DATA()/<代码>。C++11之前的方法是获取第一个元素的地址:
&sx[0]
。从一开始就覆盖对象几乎总是会导致segfault

好的,现在我们有了数据缓冲区的开始,它能够接收复数的二进制表示。但是当你声明
向量sx,它的大小为零,并且由于您不是或它的元素,向量将不会“知道”它应该调整大小。又错了。所以只要调用
调整大小

sx.resize(number_of_complex_numbers_to_store);
或使用适当的构造函数:

vector<complex<float> > sx(number_of_complex_numbers_to_store);
然后将其读入复数向量:

std::ifstream ifs("file.dat", std::ios::binary | std::ios::in);
std::vector<std::complex<float>> v(3);
ifs.read(reinterpret_cast<char*>(v.data()), 6*sizeof(float));
ifs.close();
因此,这种方法很有效

二进制文件 下面是关于二进制文件的注释,我最初将其作为注释发布

二进制文件没有“行”的概念。二进制文件中的“行”数完全取决于您在其中查看它的窗口的大小。把二进制文件想象成磁带,磁头的每个离散位置只能读取一个字节。这些字节的解释取决于您

如果一切正常,但你得到了奇怪的数字,请在
fseek
call中检查位移。多个字节的错误会产生随机值,而不是您希望得到的浮点值


当然,您可能只是读取一个向量(或数组)的
float
s,观察上面的注意事项,然后将它们转换为循环中的复数。此外,这是调试<代码> fStuts>代码>确保你开始从正确位置读取的好方法。谢尔盖:谢谢你的信息,但是我想学习使用C++来读取和处理数据的方法。我的期望是有一个向量复数(f[i]=complex(sx[i].real(),sx[i].imag())。然后,我可以应用快速傅立叶变换(fft)来计算信号的频谱。谢尔盖:对不起,那是data.dat文件,我忘了重命名它。我知道我的数据类型仍然错误。data.dat文件是从:outfile.write写入的((const char*)&buff.front(),nwrite*sizeof(complex));outfile.flush();outfile.close()谢尔盖:再次非常感谢你的详细讲座,现在我完全理解了二进制数据的样子。非常感谢…..我有一个只有零的向量复合体,我知道我做了错误的数据类型,我希望你能再次向我解释,这是我的代码:两倍总字节,向量大小;streampos开始,结束;std::ifstream ifs(“channel_1.dat”,std::ios::binary | std::ios::in);begin=ifs.tellg();ifs.seekg(0,ios::end);end=ifs.tellg();total_bytes=end-begin;vector_size=total_bytes/sizeof(复数);std::vector v(vector_size);ifs.read(reinterpret_cast(v.data()),vector_size*sizeof(复数));但我仍然只能得到零,你能帮我吗?非常感谢。谢尔盖:对不起,那是data.dat文件,我忘了重命名它。@longkhong好的,我找到了你的另一个问题。我会尽快帮助你。
std::ifstream ifs("file.dat", std::ios::binary | std::ios::in);
std::vector<std::complex<float>> v(3);
ifs.read(reinterpret_cast<char*>(v.data()), 6*sizeof(float));
ifs.close();
std::cout << v[0] << " " << v[1] << " " << v[2] << std::endl;
(1,2) (3,4) (5,6)