这是我创建二进制文件的函数
void writefile()
{
ofstream myfile ("data.abc", ios::out | ios::binary);
streamoff offset = 1;
if(myfile.is_open())
{
char c='A';
myfile.write(&c, offset );
c='B';
myfile.write(&c, offset );
c='C';
myfile.write(&c,offset);
myfile.write(StartAddr,streamoff (16) );
myfile.close();
}
else
cout << "Some error" << endl ;
}
StartAddr的值为1000
,因此预期的输出文件为:
A B C 1000 NUL NUL NUL
然而,奇怪的是我的输出文件附加了这个:data.abc
所以最后的结果是:A B C 1000 NUL NUL NUL data.abc
请帮我解决这个问题。怎么处理这个?为什么这种奇怪的行为?
答案 0 :(得分:2)
我建议您退出二进制写作并以文本格式编写数据。您已经遇到了编写数据的一些问题。您在阅读数据和可移植性方面仍然存在问题。如果你继续这条路线,会有更多的痛苦。
使用文字表示。为简单起见,您可以为每行添加一个字段,并使用std::getline
来读取它。文本表示允许您轻松地在任何文本编辑器中查看数据。尝试使用{{1}查看二进制文件!
哦,但是二进制数据太快了,文件占用的空间更少。你已经浪费了足够的时间和金钱,而不是使用二进制数据。计算机的速度和巨大的内存容量(磁盘和RAM)使二进制表示成为过去(除非在极端情况下)。
作为一种学习工具,请继续使用二进制文件。为了便于开发和快速安排(IOW,尽早完成),请使用文本表示。
搜索Stack Overflow以获取“C ++微优化”的理由。
答案 1 :(得分:1)
此代码存在几个问题。
对于初学者,如果要在流中编写单个字符,则不需要使用ostream :: write。相反,只需使用ostream :: put,如下所示:
myfile.put('A');
其次,如果要将字符串写入文件流,只需使用流插入运算符:
myfile << StartAddr;
即使在二进制模式下,这也是非常安全的。
至于您报告的特定问题,我认为问题是您正在尝试写出长度为4的字符串(StartAddr),但您已经告诉流写出16个字节。这意味着你要写出字符串内容的四个字节,然后是空终止符,然后是缓冲区之后内存中发生的9个字节。在你的情况下,这是两个空字节,然后是你之后看到的无意义的文本。要解决此问题,请更改代码以写入更少的字节,或者如果StartAddr是字符串,则只需使用&lt;&lt;。
进行编写。答案 2 :(得分:0)
使用行myfile.write(StartAddr,streamoff (16) );
,您指示myfile对象将16个字节写入从地址StartAddr
开始的流。想象一下,StartAddr
是一个16字节的数组:
char StartAddr[16] = "1000\0\0\0data.b32\0";
myfile.write(StartAddr, sizeof(StartAddr));
会生成您看到的输出。在没有看到StartAddr的声明/定义的情况下,我无法肯定地说,但是看起来你正在写出一个5字节的nul终止字符串"1000"
,然后是在StartAddr之后的下一个11字节中发生的任何事情。在这种情况下,它出现了几个nul字节后跟常量nul终止字符串"data.b32"
(编译器必须放在内存中的某个地方)跟随StartAddr。
无论如何,很明显你覆盖了一个缓冲区。
如果您尝试将16位整数类型写入流,则有两个选项,这两个选项都基于一个字节中通常有8位的事实。 “最干净”的是:
char x = (StartAddr & 0xFF);
myfile.write(x);
x = (StartAddr >> 8);
myfile.write(x);
这假设StartAddr是一个16位整数类型,并没有考虑可能发生的任何转换(例如可能将值10 [换行]转换为回车/换行序列)。
或者,您可以编写如下内容:
myfile.write(reinterpret_cast<char*>(&StartAddr), sizeof(StartAddr));