2015-08-21 82 views
1

我是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; 
    . 
    . 
    . 
} 

我已经指定格式= 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; 

这是存储窗口的Visual Studio中的输出时,我看在p

0x026A54B8 31中的值34 30 32 30 30 30 31 30 31 30 30 30 30 30 31 30 30 140200010100000100

+3

好像你正在写作ASCII并试图读回二进制。您想做什么? – pm100

+1

为了清楚起见,当你这样做时,你的工具链不会*发出警告:'fprintf(f,“%04X”,packet [i] .header);'?即发送一个'head_t'到一个'printf'-family说明符,它需要一个无符号整数?有趣。转到C/C++项目属性并打开警告级别。应该已经检测到了。 – WhozCraig

+0

使用'fwrite'会好很多,它不会指望任何格式化的输入。如果你熟悉C++做这些事情的方法(尽管它有点难),而不是旧的C方式,那么你会更好。 – Wug

回答

1

一般情况下,如果你用fprintf写,然后回读fscanf或getline;即一个面向行/ ASCII的输入机制。

如果您希望文件被构造为二进制文件,那么使用read和write进行写入和读取。

不要混合这两种机制

+0

感谢您的帮助 –

1

有几个问题:

  • 你的价值由fprintf()通过packet[i].header,并告诉fptrintf()这是一个int,而且其值应以ASCII十六进制格式写入。你的编译器可能会传递你的值为int的大小,你会得到一个可用的值。但是你的编译器可能会传递比int更多或更少的数据(因为你的头文件是一个结构体并且可能会受到对齐填充的影响),然后,你写的值将不会是你所期望的。所以它非常依赖于实现。

  • 顺便说一句,即使您的编译器传递了适当大小的值,由于字节顺序,您可能会有非可移植文件。

  • 然后,你读取你的数据,就好像它是二进制文件(不打开文件为“rb”反正会造成严重破坏)。因此,您只会读取部分ASCII数据,并且完全不同地解释编码(即,您写'1',但您会读取0x31)。那也行不通。你必须按照与你写的逻辑相同的逻辑,用fscanf()来阅读它。但是,如上所述,这是非常依赖于实施的。

作为很不错的选择,我会建议你打开该文件作为二进制fstreams,使用ios::binary,并使用write()/read()写的内存块,使用您的数据元素,并且其确切大小的地址。

作为更便携的替代,可以使用文本文件流,和过载<<>>head_t类型为使用很好的控制(即固定的字节顺序)十六进制格式。

+0

谢谢,我明白了.. –