我是C ++编码的新手。我的应用程序需要将变量写入文件,然后我想再次阅读它们来做一些工作。
我将值分配给变量然后我转储到文件上但是当我读取文件并检查变量时,它分配了不同的值。 以下是我正在使用的3种结构。
struct fence_t
{
uint8_t b:1;
uint8_t fence_1:2;
uint8_t fence_2:2;
uint8_t res:3;
};
struct head_t
{
uint8_t format;
fence_t fence;
};
struct pack_t
{
head_t header;
.
.
.
}
我已指定format = 2
packet[i].header.format=2;
packet[i].header.fence.b=0;
packet[i].header.fence.fence_1=2;
packet[i].header.fence.fence_2=2;
packet[i].header.fence.res=0;
这是我打开文件并在其上转储数据的方式。我希望以十六进制格式写入值。
f = fopen("packets.txt","w");
fprintf(f, "%04X", packet[i].header);
现在在另一个函数中我想读取文件。
ff.seekg(0,ios::end);
size=ff.tellg();
memblock = new pack_t [size/sizeof(pack_t)];
ff.seekg(0,ios::beg);
ff.read((char *)memblock,size);
void * p = (void *)memblock;
for(int i=0;i<3;i++)
{
struct q_entry_t t = {i, p};
queue1.push_back(t);
p = (void *)((uintptr_t)p+64);
}
当我检查格式的值时,它会显示1。
cout<<((head_t *)p)->format<<endl;
当我查看p
的值时,这是Visual Studio中内存窗口的输出0x026A54B8 31 34 30 32 30 30 30 31 30 31 30 30 30 30 30 31 30 30 140200010100000100
答案 0 :(得分:1)
有几个问题:
您按packet[i].header
中的值传递fprintf()
,并告诉fptrintf()
该int
并且其值应以ascii十六进制格式写入。您的编译器可能会以int
的大小传递您的值,并且您将获得可用的值。但是你的编译器也可能传递比int更多或更少的数据(因为你的头是一个结构,可能会受到对齐填充),然后,你要写的值将不是你所期望的。所以它非常依赖于实现。
顺便说一下,即使你的编译器传递了一个适当大小的值,由于字节顺序,你也可能有不可移植的文件。
然后,您将数据读取为二进制文件(不打开文件,因为“rb”无论如何会造成严重破坏)。所以你只会读取ascii数据的一部分,并完全不同地解释编码(即你写'1'但你会读到0x31)。那也行不通。根据与您编写的逻辑相同的逻辑,您必须使用fscanf()
读取它。但如上所述,这非常依赖于实现。
作为简单的替代方案,我建议您使用ios::binary
将文件作为二进制fstream打开,并使用write()
/ read()
来编写内存块,使用您的地址数据元素及其确切大小。
作为一种更便携的替代方案,您可以使用文本文件流,并为类型<<
重载>>
和head_t
以使用良好控制(即固定字节顺序)十六进制格式。
答案 1 :(得分:1)
一般情况下,如果你用fprintf写,那么用fscanf或getline回读;即面向行/ ASCII的输入机制。
如果您希望文件是二进制结构,则使用read进行写入和读取。
不要将这两种机制混合起来