在试图找到这个问题的答案时,我写了这个小测试程序:
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
void writeFile() {
int data[] = {0,1,2,3,4,5,6,7,8,9,1000};
std::basic_ofstream<int> file("test.data", std::ios::binary);
std::copy(data, data+11, std::ostreambuf_iterator<int>(file));
}
void readFile() {
std::basic_ifstream<int> file("test.data", std::ios::binary);
std::vector<int> data(std::istreambuf_iterator<int>(file),
(std::istreambuf_iterator<int>()));
std::copy(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
int main()
{
writeFile();
readFile();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它按预期工作,将数据写入文件,并在读取文件后,正确打印:
0 1 2 3 4 5 6 7 8 9 1000
Run Code Online (Sandbox Code Playgroud)
但是,我不确定是否存在任何陷阱(除了字节问题,在处理二进制数据时总会有这些问题)?这是允许的吗?
在 char 或 wchar_t 之外的任何对象上实例化任何 iostream 类或 basic_string,而不提供特定的自定义特征类,都是未定义的行为;我见过的大多数库确实定义了它来执行某些操作,但该定义通常没有指定,并且 VC++ 和 g++ 之间的定义不同(我看过的两种情况)。如果您定义并使用自己的特征类,则某些功能应该可以工作。
对于几乎所有格式化插入器和提取器(<<和
>>运算符),istream并ostream委托给语言环境中的各个方面;如果使用其中任何一个,您必须采取措施确保它们也能正常工作。(这通常意味着提供一个新的 numpunct 方面。)
即使您只使用streambuf(如您的示例中所示),filebuf
也会使用 codecvt 方面。并且实现不需要提供编解码器,如果提供了,则可以在其中执行几乎任何操作。由于filebuf总是对char文件进行写入和读取,因此该翻译必须执行某些操作。事实上,我对你的代码能够工作感到非常惊讶,因为这个。但您仍然不知道磁盘上实际有什么,这意味着您无法记录它,这意味着您将来无法读取它。
如果您的目标是写入二进制数据,那么第一步应该是定义二进制格式,然后编写实现它的读写函数。可能使用 iostream << 和 >> 语法,并且可能使用 abasic_streambuf<char>来表示实际的输入和输出;abasic_streambuf<char>您已小心地将“C”区域设置注入其中。或者,不要定义自己的二进制格式,而只需使用现有的格式,例如 XDR。(本段所有内容都假设您要保留数据,并在以后读取它。如果这些只是临时文件,用于在单次运行期间将临时内部数据溢出到磁盘,并将在程序执行结束时删除,更简单的解决方案是有效的。)
| 归档时间: |
|
| 查看次数: |
299 次 |
| 最近记录: |