2011-11-28 89 views
4

我使用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 

现在我想将此矢量保存到我的硬盘驱动器。如何以及什么是最快的方式来做到这一点?数据的大小相当大(〜1/2   GB)。我试过如下:

ofstream outfile("allMyNumbers.txt", ios::out | ios::binary); 
outfile.write(&testDump[0], testDump.size()); 

但我发现了以下错误:

cannot convert parameter 1 from 'unsigned short *' to 'const char *' 

什么来完成我的任务,是用最快的方法来保存矢量文件的最快方法?

*的平台是Windows 7

+0

这肯定要取决于您定位的平台。 –

+0

内存映射文件可能适用于此,具体取决于平台。 – OSH

+0

我的平台是Windows 7.编辑 –

回答

3

一个独立于平台的技术是使用一个ostream_iterator您的矢量级持有的类型。由于您的矢量包含的类型已经为operator<<对于ostream类类型过载,所以对于矢量类型,您不应该为ostream_iterator类实例化模板。然后,您将结合ostream_iterator和STL中的copy算法遍历您的向量,并将原始字节序列化到文件中。使用operator<<将使用比使用ofstream::write更多的数据,该数据将原始二进制数据写入磁盘,但具有序列化数据的优点,使其可在任何平台上独立读取。

因此,例如:

vector<unsigned short> testDump(2048000000); 
//...fill in your vector 

ofstream outfile("allMyNumbers.txt", ios::out | ios::binary); 

//tab-delinate the data 
ostream_iterator<unsigned short> o_iter(outfile, "\t"); 
copy(testDump.begin(), testDump.end(), o_iter); 
+2

也许值之间的分隔符是有序的。当然,提问者并未指定将来可以读取数据,但我认为这是可以假设的。 –

+0

绝对是一个好主意......虽然对于二进制文件,它必须是某种类型的“魔术”数字,而不是简单的字符分隔符,除非该字符不会成为实际输出本身的一部分开始用。典型地,二进制文件将具有指向原始数据部分的指针的头部以及关于每个可读数据部分的大小的规范,以避免分隔符模糊。 – Jason

+0

感谢您的建议。如果我可能会问,我该怎么做(它不需要保持二进制,我可以使用十进制)。顺便说一句,它是永恒的完成。它仍然没有完成(到目前为止3分钟) –

3

可以只投的指针。

outfile.write(reinterpret_cast<char*>(&testDump[0]), testDump.size() * sizeof(unsigned short)); 

注意,生成的文件在某种程度上这是特定于您的特定平台/执行格式化。所以你不一定在不兼容的机器上以明显的方式阅读它。

在Windows上,这将为您提供一个400MB-ish文件,每个204800000对字节代表一个小端无符号短整型。

这应该是相当快的。我发现很难相信你的任务真的是“使用最快的方法”来保存数据。怎么会有人知道你的代码真的是最优的,没有其他代码可以使它的速度提高一纳秒?还有什么额外的努力来削减纳秒?等等。

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

+0

我认为OP只有大约400MB的数据。 –

+0

@Kerrek:你说得对,这个问题已经被编辑过。我相信示例代码中的数字,而不是文本。 –

+0

@SteveJessop:你的方法超快(少于一秒)。但是,当我打开输出文件时,出现奇怪的符号。你有什么建议吗?我还想在数据点之间添加分隔符,是否有一种简单的方法可以实现这一点? –

1

一个串行化的交叉平台方式是将注意力集中在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)); 
} 

htole16(主机为16个整数小端)的实现如下:

对于x86,x64系统:

unsigned short htole16(unsigned short x) 
{ 
    return x; 
} 

对于像Sparc/PowerPC这样的大型机器(尽管没有一个会运行Windows 7)

unsigned short htole16(unsigned short x) 
{ 
    return _byteswap_ushort(x); 
} 
+0

这只是“跨平台”,因为您已经预先定义了二进制数据将如何格式化......如果读者不知道数据的商定格式是什么,那么它不是“跨平台” ”。 – Jason

+0

阅读器(程序)在尝试读取数据之前,还需要知道数据使用ASCII制表符分隔符号。此外,在网络协议中使用使用大端格式的类似技术来实现跨平台数据表示。字节顺序被称为“网络字节顺序”,通常使用的C函数是htons()和ntohs()。以上是这种(流行)技术的变体。 – ritesh

+0

我意识到您正在使用网络字节顺序标准化为多字节数据块的大端表示形式的网络技术的变体。我会给你一个+1,否则我们只会在圈子里说话,因为它的标准比其他标准更“标准化”:-) – Jason