fwrite,fgets二进制文件回读问题 [英] fwrite, fgets binary file readback problem

查看:134
本文介绍了fwrite,fgets二进制文件回读问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找出为什么我无法正确读回二进制文件。


我有以下联盟:


#define BITE_RECORD_LEN 12

typedef union {

unsigned char byte [BITE_RECORD_LEN];

struct {

unsigned char type; / * 0类型* /

unsigned char sn [3]; / * 1-3序列号* /

unsigned char date_yy; / * 4日期 - 年* /

unsigned char date_mm; / * 5日期 - 月* /

unsigned char date_dd; / * 6日期 - 日* /

unsigned char flight_leg; / * 7 Number * /

unsigned char time_hh; / * 8时间 - 小时* /

unsigned char time_mm; / * 9时间 - 分钟

* /

unsigned char etime [2]; / * 10-11经过时间* /


struct {/ * 12纠正措施

状态* /

unsigned char spare :6; / *位5-0,备用* /

unsigned char maint_alert:1; / * bit 6,Alert,

1 = alert * /

unsigned char serviced:1; / *第7位,状态,

1 =服务错误* /

} caa_status;

}字段;

} myrecord;


我打开它:(省略一些细节)


fp = fopen(filename," wb");


我把它写成:


myrecord temp_fault_record;

fwrite(.byte,BITE_RECORD_LEN,1,fp );


我对ReadFile的调用:

fopen(文件,rb);


m_fault_record =(myrecord *)malloc(size);

int num = ReadFile(file_des,(unsigned char *)m_fault_record,

size);

我通过fgets读回来:


int ReadFile(FILE * fp,unsigned char * buf,int count)

{

if(fgets((char *)buf,count,fp)== NULL)

{

debug_message(" ERROR ReadFile read data" );

返回-1;

}

返回计数;

}

我的问题是在大约6条记录之后(I l oop over

''m_fault_record'')

我的数据无效。上面的''尺寸'是通过统计文件来计算的

正在阅读

并且是正确的。


At这一点我花了几个小时解析代码到一个小的
可执行文件并试图找到没有运气的问题,这就是为什么

我发布

这里要问。我也为fgets看了谷歌一段时间。我b $ b看到一些人

谈论fread()的二进制文件,但似乎更多的是

效率而不是需要
在我的情况下



如果我错过了任何细节,请回复并添加它们。我想

我得到了一切。

我感谢所有评论。其他人可能会看到我在做什么

错了。


作为旁注,我将这段代码从c移植到c ++(不应该是

问题)。

旧代码使用CVI / Labview进行ReadFile调用,我没有使用

而我只是

将它移植到我认为相当的东西上,它应该很简单,但显然

它不是。


谢谢,

Jeff

解决方案

文章< 51 ************* *********************@a9g2000prl.g ooglegroups.com>,

Jeff< je ** @ rahul.netwrote:


>我试图弄清楚为什么我无法正确读回二进制文件。


>我有以下联盟:


> #define BITE_RECORD_LEN 12
typedef union {

unsigned char byte [BITE_RECORD_LEN];

struct {

unsigned char type; / * 0类型* /

unsigned char sn [3]; / * 1-3序列号* /

unsigned char date_yy; / * 4日期 - 年* /

unsigned char date_mm; / * 5日期 - 月* /

unsigned char date_dd; / * 6日期 - 日* /

unsigned char flight_leg; / * 7 Number * /

unsigned char time_hh; / * 8时间 - 小时* /

unsigned char time_mm; / * 9时间 - 分钟
* /

unsigned char etime [2]; / * 10-11经过时间* /


struct {/ * 12纠正措施
状态* /

unsigned char spare:6; / *位5-0,备用* /

unsigned char maint_alert:1; / * bit 6,Alert,

1 = alert * /

unsigned char serviced:1; / *第7位,状态,

1 =服务错误* /

} caa_status;

}字段;
} myrecord;



检查sizeof myrecord.field是否与BITE_RECORD_LEN

相同(交叉检查myscord的大小是不是BITE_RECORD_LEN )


编译器允许在结构元素之间放置未命名的填充

用于任何目的(虽然对位域填充有一些限制。)

我不会 - 在意外的无符号字符之间填充 - 但是

这是可能的。特别是,我担心caa_status结构可能会在它之前或之后结束填充。

我注意到你使用了unsigned char位域。在C89 / C90中,

位域的基本类型必须是(可能是合格的)

int,signed int或unsigned int。 C99将_Bool添加到允许的基础

类型列表,以及或其他一些实现定义的类型。

因此,您显示的结构违反了Contraint,除非您

正在使用C99,你的实现将char定义为允许的基类型。

结果*可能*是每个unsigned char基类型
$ b $ caa_status中的b被静默转换为unsigned int,caa_status

因此最终变得像int一样大而不是像char一样大

隐含在你的代码。这就是为什么你的

字段子结构可能不是BITE_RECORD_LEN的具体原因。
-

人们可以做什么令人惊讶当他不得不这样做的时候,以及当他们没有必要的时候,大多数男人都会这样做。

- Walter Linn


Jeff< je ** @ rahul.netwrites:


我试图找出为什么我无法正确读回二进制文件。



[...]


if(fgets((char *)buf,count,fp )== NULL)



fgets不适合读取二进制数据。使用fread。

-

char a [] =" \ n .CJacehknorstu" ;; int putchar(int); int main(void){unsigned long b []

= {0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x11f6},* p

= b,i = 24; for(; p + = !* p; * p / = 4)开关(0 [p]& 3)情况0:{return 0; for(p - ; i - ; i - )case +

2:{i ++; if(i)break; else default:continue; if(0)case 1:putchar(a [i& 15]); break;}}}


6月5日下午12:42,Ben Pfaff< b ... @ cs.stanford.eduwrote:


>

fgetsis不适合读取二进制数据。使用fread。



是的,修正了它。感谢你们两位的所有信息!

Jeff


Im trying to figure out why I cant read back a binary file correctly.

I have the following union:

#define BITE_RECORD_LEN 12
typedef union {
unsigned char byte[BITE_RECORD_LEN];
struct {
unsigned char type; /* 0 Type */
unsigned char sn[3]; /* 1-3 Serial Number */
unsigned char date_yy; /* 4 Date - Year */
unsigned char date_mm; /* 5 Date - Month */
unsigned char date_dd; /* 6 Date - Day */
unsigned char flight_leg; /* 7 Number */
unsigned char time_hh; /* 8 Time of Day - Hours */
unsigned char time_mm; /* 9 Time of Day - Minutes
*/
unsigned char etime[2]; /* 10-11 Elapsed Time */

struct { /* 12 Corrective Action
Status */
unsigned char spare: 6; /* bits 5-0, Spare */
unsigned char maint_alert: 1; /* bit 6, Alert,
1 = alert */
unsigned char serviced: 1; /* bit 7, Status,
1 = fault serviced */
} caa_status;
} field;
} myrecord;

I open it with: (some details ommitted)

fp = fopen(filename,"wb");

I write it as:

myrecord temp_fault_record;
fwrite(.byte, BITE_RECORD_LEN, 1, fp);

my call to ReadFile:
fopen(file, "rb");

m_fault_record = (myrecord *) malloc (size);
int num = ReadFile (file_des, (unsigned char *)m_fault_record,
size);

I read it back via fgets:

int ReadFile(FILE *fp, unsigned char *buf, int count)
{
if (fgets((char *)buf, count, fp) == NULL)
{
debug_message("ERROR ReadFile reading data");
return -1;
}
return count;
}

My problem is that after about 6 records (I loop over the
''m_fault_record'')
my data is not valid. ''size'' above is calculated by stat''ing the file
being read
and is correct.

At this point Ive spent several hours parsing down the code to a small
executable and trying to find the problem with no luck, which is why
Im posting
this here to ask. Ive looked at google for a while too for fgets. I
saw some people
talking about fread() for binary files, but it seemed more for
efficiency than a need
in my case.

If Ive missed any details please just reply and Ill add them. I think
I got everything.
I appreciate any and all comments. Someone else may see what Im doing
wrong.

As a sidenote, Im porting this code from c to c++ (which shouldnt be a
problem).
The old code used CVI/Labview for the ReadFile call, which I dont have
and I just
ported it to what I thought would be equivalent, and it should be
easy, but apparently
its not been.

Thanks,
Jeff

解决方案

In article <51**********************************@a9g2000prl.g ooglegroups.com>,
Jeff <je**@rahul.netwrote:

>Im trying to figure out why I cant read back a binary file correctly.

>I have the following union:

>#define BITE_RECORD_LEN 12
typedef union {
unsigned char byte[BITE_RECORD_LEN];
struct {
unsigned char type; /* 0 Type */
unsigned char sn[3]; /* 1-3 Serial Number */
unsigned char date_yy; /* 4 Date - Year */
unsigned char date_mm; /* 5 Date - Month */
unsigned char date_dd; /* 6 Date - Day */
unsigned char flight_leg; /* 7 Number */
unsigned char time_hh; /* 8 Time of Day - Hours */
unsigned char time_mm; /* 9 Time of Day - Minutes
*/
unsigned char etime[2]; /* 10-11 Elapsed Time */

struct { /* 12 Corrective Action
Status */
unsigned char spare: 6; /* bits 5-0, Spare */
unsigned char maint_alert: 1; /* bit 6, Alert,
1 = alert */
unsigned char serviced: 1; /* bit 7, Status,
1 = fault serviced */
} caa_status;
} field;
} myrecord;

Check that sizeof myrecord.field is the same as BITE_RECORD_LEN
(and it wouldn''t hurt to crosscheck that sizeof myrecord is BITE_RECORD_LEN)

Compilers are allowed to put unnamed padding between structure elements
for any purpose (though there are some restrictions on bitfield padding.)
I would not -expect- padding between consequative unsigned char, but
it is a possibility. In particular, I would be concerned that the
the caa_status struct might end up with padding before or after it.
I notice that you have used unsigned char bitfields. In C89/C90,
the base type for a bitfield must be a (possibly qualified)
int, signed int, or unsigned int. C99 adds _Bool to the allowed base
type list, along with "or some other implementation-defined type".
Thus the structure you show violates a Contraint unless you
are using C99 and your implementation defines char as an allowed base type.
The result *could* be that each of those unsigned char base types
in caa_status is silently converted to unsigned int, with caa_status
thus ending up as large as an int rather than "as large as a char"
that is implicit in your code. This is a concrete reason why your
field substructure might not be BITE_RECORD_LEN .
--
"It is surprising what a man can do when he has to, and how
little most men will do when they don''t have to."
-- Walter Linn


Jeff <je**@rahul.netwrites:

Im trying to figure out why I cant read back a binary file correctly.

[...]

if (fgets((char *)buf, count, fp) == NULL)

fgets is not appropriate for reading binary data. Use fread.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}


On Jun 5, 12:42 pm, Ben Pfaff <b...@cs.stanford.eduwrote:

>
fgetsis not appropriate for reading binary data. Use fread.

Yep, that fixed it. Thanks for all the info from both of you!
Jeff


这篇关于fwrite,fgets二进制文件回读问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆