C++ 将大矢量数字保存到硬盘驱动器

C++ 将大矢量数字保存到硬盘驱动器,c++,memory,vector,C++,Memory,Vector,我使用unsigned short类型的向量在RAM中分配了一大块连续字节 vector<unsigned short> testDump(204800000); for(int k = 0; k<204800000; k++) testDump[k] = 9; \\ This is different in my real program 但我得到了以下错误: cannot convert parameter 1 from 'unsigned short *' t

我使用unsigned short类型的向量在RAM中分配了一大块连续字节

vector<unsigned short> testDump(204800000);

for(int k = 0; k<204800000; k++)
    testDump[k] = 9; \\ This is different in my real program
但我得到了以下错误:

cannot convert parameter 1 from 'unsigned short *' to 'const char *'
完成我的任务的最快方法是什么,即使用最快的方法将向量保存到文件中


*该平台是Windows 7。

一种与平台无关的技术是使用
ostream\u迭代器
作为vector类所持有的类型。因为向量包含的类型已经为
操作符重载,所以您可以强制转换指针

outfile.write(reinterpret_cast<char*>(&testDump[0]), testDump.size() * sizeof(unsigned short));
outfile.write(reinterpret_cast(&testDump[0]),testDump.size()*sizeof(unsigned short));
请注意,生成的文件的格式是特定于特定平台/实现的。因此,在一台不兼容的机器上,您不必以显而易见的方式将其读回

在Windows上,这将为您提供一个400MB的ish文件,204800000对字节中的每一对都表示一个小的endian无符号短字符

这应该相当快。我发现很难相信你的任务真的是“用最快的方法”保存数据。谁会知道你的代码真的是最优的,没有其他代码比你的代码快一纳秒?那么,花额外的精力去刮去一纳秒又有什么意义呢?等等


当然,使用快速流压缩算法来减少所需的磁盘空间可能会更快,因为操作可能会受到磁盘I/O的限制。但是代码会更复杂,它是否有用取决于数据的可压缩性。

一种跨平台的串行化方法是只关注简短的little-endian表示,然后抛掉所有的缺点。这将避免Jason解决方案中的ASCII数据膨胀,同时实现跨平台

所以,我就这么做

ofstream outfile("allMyNumbers.data", ios::out | ios::binary);
for(int k = 0; k < testDump.size(); k++)
{
    unsigned short leData = htole16(testDump[k]);    
    outfile.write(&leData, sizeof(leData));
}
对于诸如Sparc/PowerPC这样的大端机器(尽管这些机器都不会运行Windows 7)


这肯定取决于您的目标平台。内存映射文件可能适合这里,具体取决于平台。我的平台是Windows 7。编辑您的数据大小不是~1/2 GB,更接近3.81 GB。哦,抱歉。我有一个额外的0。编辑。谢谢,可能值之间有一个分隔符。诚然,提问者并没有明确说明将来可以读回数据,但我认为这是可以假设的。绝对是个好主意。。。尽管对于二进制文件,它必须是某种类型的“魔法”数字,而不仅仅是一个字符分隔符,除非该字符从一开始就不是实际输出本身的一部分。通常,二进制文件会有一个标头,其中包含指向原始数据部分的指针和每个可读数据部分大小的规范,以避免分隔符的歧义。谢谢您的建议。如果我可以问的话,我会怎么做(它不需要保持二进制,我可以使用dec)。顺便说一句,这要花很长时间才能完成。它还没有结束(到目前为止还有3分钟)@Jason:在你的代码中,数字都是以base-10ascii的形式写入流的。文件是以二进制模式打开的这一事实与此无关。因此,数字0-9以外的任何字符都将用作分隔符。如果值是以二进制格式保存的,那么可以安排不需要分隔符,这些值可以按固定宽度写入。@RoronoaZoro:根据Steve的评论,因为您实际上是在用ASCII而不是存储在向量中的原始两字节二进制数据写入十进制数,如果大多数数字的长度大于两个十进制数字,那么您的书写量将远远超过400MB。其次,只需向
ostream\u迭代器的构造函数添加第二个参数,就可以添加任何ASCII分隔符。。。只需将分隔符设置为任何非数字字符。这种方法的缺点是您会得到数据膨胀。。。好处是序列化过程是独立于平台的。我认为OP只有大约400MB的数据。@Kerrek:你说得对,这个问题已经编辑好了。我相信示例代码中的数字,而不是文本。@SteveJessop:您的方法速度非常快(不到1秒)。然而,当我打开输出文件时,我得到了奇怪的符号。你有什么建议吗?我还想在数据点之间添加分隔符,有没有简单的方法呢?@Roronoa:在什么地方打开输出文件?文本编辑器?当然,里面有奇怪的符号,因为我的代码没有把值写成文本。我认为您需要问另一个问题,指定此文件的实际用途,并询问您应将其保存为何种格式。@SteveJessop:很抱歉造成混淆/含糊不清。我试图存储到硬盘的值是像素值(从0到255)。我想稍后使用Matlab将它们转换为图像。我将文件保存为.txt并尝试在文本编辑器中打开它。这只是“跨平台”,因为您已经预定义了二进制数据的格式。。。如果读者不知道约定的数据格式是什么,那么它不是“跨平台”的。读者(程序)在尝试读取数据之前,还需要知道数据是ASCII制表符分隔的符号。此外,在网络协议中使用类似的使用big-endian格式的技术来实现跨平台数据表示。字节顺序称为“网络字节顺序”,常用的C函数是htons()和ntohs()。以上是这种(流行的)技术的一种变体。我知道您正在使用一种网络技术的变体,其中网络字节顺序在多字节数据块的大端表示上标准化。我会给你一个+1,否则我们只会在圈子里讨论谁的标准比另一个标准更“标准化”:-)@Jason:如果你想要一个“标准”表示,那么JSON可能不是个坏主意
outfile.write(reinterpret_cast<char*>(&testDump[0]), testDump.size() * sizeof(unsigned short));
ofstream outfile("allMyNumbers.data", ios::out | ios::binary);
for(int k = 0; k < testDump.size(); k++)
{
    unsigned short leData = htole16(testDump[k]);    
    outfile.write(&leData, sizeof(leData));
}
unsigned short htole16(unsigned short x)
{
    return x;
}
unsigned short htole16(unsigned short x)
{
    return _byteswap_ushort(x);
}