c++ 用python structt和void把数据输入之后我的输出没有东西,求解怎么才能让输出有东西

[精彩] 我的程序里边,为什么fwrite没有把数据写到文件里边啊? - ChinaUnix.net
[精彩] 我的程序里边,为什么fwrite没有把数据写到文件里边啊?
http://www.chinaunix.net 作者:&&发表于: 18:12:23
引用:#include&&stdio.h&;
#include&"err_exit.h"
struct&record{
&&int&
&&char&login[9];
};
char&*logins[]={"user1","user2","user3","user4","user5"};
void&putrec(FILE&*fp,int&i,struct&record&*r)
{
&&fseek(fp,(long)i*sizeof(struct&record),0);
&&[color=red]fwrite((char&*)r,sizeof(struct&record),1,fp);[/color]
}
int&main(void)
{
&&int&i;
&&FILE&*
&&struct&record&
&&
&&if&((fp&=&fopen("datafile","w"))==NULL)
&&&&&err_exit("datafile");
&&&&&
&&&for(i=4;i&;=0;i--)
&&&&&&{
&&&&&&&&&rec.uid=i;
&&&&&&&&&strcpy(rec.login,logins);
&&&&&&&&&putrec(fp,i,&rec);
&&&&&&&}
&&&&&&&fclose(fp);
&&&&&&&exit(0);
}
执行该程序后datafile文件是空的啊
& 回复于: 11:15:24
whyglinux帮忙看一下啊,谢谢
& 回复于: 11:18:38
fwrite()返回码
& 回复于: 11:25:08
程序没有问题
& 回复于: 11:26:31
楼上的意思是说要看fwrite()返回什么内容吗?
& 回复于: 11:28:47
if&((fp&=&fopen("datafile","w"))==NULL)&
改成
if&((fp&=&fopen("datafile","wb"))==NULL)
& 回复于: 11:32:34
b是binary吧,还是不行啊
是不是系统兼容的问题,我的系统是solaris9
& 回复于: 11:38:18
void&putrec(FILE&*fp,int&i,struct&record&*r)&
{&
fseek(fp,(long)i*sizeof(struct&record),0);&
fwrite((char&*)r,sizeof(struct&record),1,fp);&
}&
问题在这里。你上来就&i=4,让文件指针转到那个地方。
可是此时文件里还没有东西呢,文件指针怎么会转到那个地方呢。
---------------------------
& 回复于: 11:43:54
就象前面&飞灰橙&告诉你的,原来的程序没有问题。你说datafile文件是空的,有什么根据没有?检查一下文件的大小不就知道了。在我这里它的大小为&80&字节。
& 回复于: 12:26:42
仔细检查一下吧,极可能是人为原因。
& 回复于: 12:57:35
引用:原帖由&"liangtf"]仔细检查一下吧,极可能是人为原因。&发表:
逻辑上都N处错误了,还“极可能”“人为”?
I服了U!
& 回复于: 13:08:01
&;&;&逻辑上都N处错误了,还“极可能”“人为”?
不知&FH&所说的&N&处错误表现在哪里,能给我们说说吗?我实在看不出楼主的程序有什么明显的错误。
& 回复于: 13:10:49
引用:原帖由&"FH"&发表:
逻辑上都N处错误了,还“极可能”“人为”?
I服了U!
不懂,望指点。
& 回复于: 13:13:56
引用:原帖由&"zkyguanl"&发表:void&putrec(FILE&*fp,int&i,struct&record&*r)&
{&
fseek(fp,(long)i*sizeof(struct&record),0);&
fwrite((char&*)r,sizeof(struct&record),1,fp);&
}&
问题在这里。你上来就&i=4,让文件指针转到那个地方。..........
程序没有问题.即使文件刚刚生成,文件指针也是可以移动的,请查阅APUE.中文版39页.
"文件位移量可以大于文件当前长度,...形成空洞文件"
上述的代码运行结果如下
===============================================
在UE中打开
&&&&user1&烫烫烫&&&user2&烫烫烫&&&user3&烫烫烫&&&user4&烫烫烫&&&user5&烫烫烫
文件大小为80&字节&(80&字节)
所以,说明执行成功,写入四条记录,大小为4*sizeof(record)
===============================================
回答问题,最好不要主管臆断,试验下先,更不要说什么"人为错误的"唯心主义论调.
& 回复于: 13:15:51
虚心接受。
& 回复于: 13:19:05
下面是用16进制打开的文件datafile
可以分析,已经成功写入了数据.
& 回复于: 13:20:42
引用:原帖由&"windflowers1976"&发表:龅拇?朐诵薪峁?缦?
===============================================
在UE中打开
&&&&user1&烫烫烫&&&user2&烫烫烫&&&user3&烫烫烫&&&user4&烫烫烫&&&user5&烫烫烫
文件大小为80&字节&(80&字节)
所以,说..........
喂,老兄你怎么知道没试验???可我用的是MDK的Linux系统
程序是没问题的,当然就出在系统或是其它方面的原因了,和程序代码本身原因比这难道不能说成是人为原因吗?
难道楼主成功了硬要说是空文件?!
主要是帮助别人解决问题,而我们不在用户环境下,还能怎么做?
不要妄下结论!
& 回复于: 13:36:18
呵呵,不用生气.言语不当见谅.不是说你没有试验.
程序是没有问题的,不会产生空文件.
如果楼上的同志还以为是空文件,那请用WINDOWS&UE和UNIX的HD命令打开看看.
& 回复于: 14:41:37
【逻辑错误】看这里:
for(i=4;i&;=0;i--)&
先用i=4调用putrec,对于空文件,fseek会怎样?
fseek和fwrite的返回码都不判!
对于空文件来说,最后写出的文件中应该包含几个记录,谁能说清楚?应该是3条记录而不是5条记录吧?
是不是产生空洞好像和系统相关吧?
& 回复于: 14:43:45
谢谢,各位的关注,我的本意是倒着取数据,写到datafile里后,能看到正序的数据,主要是实验fseek的功能
vi&datafile
显示内容如下(属性显示大小80k),现在有两个问题:
1.显示的内容显然不是我所要得到的,即使是大家实验的结果有点接近,怎么把"烫"去掉呢?
2.在我的solaris系统中直接打开该文件,看到的是空白的,也就是我前面所谓的程序没有写东西
引用:ser1^C\377\314^Auser2^C\377\314^Buser3^C\377\314^Cuser4^C\377\314^Duser5
^C\377\314
& 回复于: 14:49:29
引用:原帖由&"fwizard"]&发表:
1.什么是你想要的结果.
2.vi&大概不能直接打开二进制文件吧.
3.用hd&datafile&看文件的内容.
4.我去SUN&和LINUX&SCO&HP&下跑跑看.
5.少等.
& 回复于: 15:05:55
这个程序主要想说明fseek函数的定位功能,它按逆序取出结构数组logins的各个元素并按此顺序将它们输出到文件中,但是输出的数组元素在文件中仍然按元素顺序排列.为此,在函数putrec中用fwrite每输出一个结构成员之前,先掉用fseek定位该元素在文件中的位置,这个位置是相对文件开始的位置,其偏移量为i*sizeof(struct&record)个字节,i的数组元素下标.
& 回复于: 15:11:16
在LINUX&SCO&HP-UX&下测试;我手头的SUN&没有编译器;
#include&&stdio.h&;&
#include&&stdlib.h&;
//#include&"err_exit.h"&
struct&record{&
int&&
char&login[9];&
};&
char&*logins[]={"user1","user2","user3","user4","user5"};&
void&putrec(FILE&*fp,int&i,struct&record&*r)&
{&
&&&fseek(fp,(long)i*sizeof(struct&record),0);&
&&&fwrite((char&*)r,sizeof(struct&record),1,fp);&
}&
int&main(void)&
{&
&&&int&i;&
&&&FILE&*&
&&&struct&record&&
&&&if&((fp&=&fopen("datafile","w"))==NULL)&
&&&&&&//err_exit("datafile");&
&&&{
&&&&&&perror("open");
&&&&&&exit(-1);
&&&}
&&&for(i=4;i&;=0;i--)&
&&&{&
&&&&&&memset&(&&rec,&0,&sizeof(struct&record)&);
&&&&&&rec.uid=i;&
&&&&&&strcpy(rec.login,logins);&
&&&&&&putrec(fp,i,&rec);&
&&&}&
&&&fclose(fp);&
&&&exit(0);&
}
& 回复于: 15:12:20
& 回复于: 15:16:12
WINDOWS&vc6测试
& 回复于: 15:22:55
引用:原帖由&"FH"&发表:【逻辑错误】看这里:
fseek和fwrite的返回码都不判!
如果是按照楼主最后说明的要求,同意FH的说法.
不判断返回码就好像把1000$钱往口袋里放却不管口袋有没漏洞,放进去就行.
& 回复于: 15:34:19
谢谢楼上的大哥
对二进制文件一直没有深的认识
1?写入文件的是数组或者是结构体数据,自然就是二进制文件了?
2?二进制文件直接打开后什么都看不到吗?
3?在userx后面总是有一个多的东西,是怎么出来的,我这里solaris下more之后后面都有个况字
引用:user1况user2况user3况user4况user5况
& 回复于: 16:12:00
1?写入文件的是数组或者是结构体数据,自然就是二进制文件了?&
2?二进制文件直接打开后什么都看不到吗?&
如果对应的&ascii&值是不可见字符,就有可能看不到或者乱码
3?在userx后面总是有一个多的东西,是怎么出来的,我这里solaris下more之后后面都有个况字&
这个就是乱码,建议直接看二进制数据&"%02x"&&:em17:&&偶的笨办法
& 回复于: 13:33:07
我试了一下读出文件
#include&&stdio.h&;&
struct&record{&
int&&
char&login[9];&
};&
int&main(void)&
{&
int&i;&
FILE&*&
struct&record&&
if&((fp&=&fopen("datafile","r"))==NULL)&
{
&&printf("open&file&error");
&&
}
struct&record&a;
for(i=4;i&;=0;i--)&
{&
fread(&a,sizeof(struct&record),1,fp);
printf("%d--%s\n",a.uid,a.login);
}&
fclose(fp);&
exit(0);&
}&
可以读出,
0--user1
1--user2
。。。。
是否是,系统自己加入的某些字符,用于分割结构体
& 回复于: 14:04:51
引用:原帖由&"jiutiao2004"&发表:&
int&main(void)&
{&
int&i;&
FILE&*&
struct&record&&
if&((fp&=&fopen("datafile","r"))==NULL)&
{
&&printf("open&file&error");
&&
}
struct&record&a;
for(i=4;i&;=0;i--..........
NOD.
& 回复于: 19:57:02
把这个帖子中出现的一些问题归纳了一下。如有不同看法,欢迎继续讨论。
1.&楼主给出的程序是正确的,执行程序能得到预期的结果。这个程序其实出自一本介绍在&Unix&下&C&编程的书(具体叫什么记不得了),以前看到过。
2.&楼主刚开始说产生的文件是“空文件”(真正的结果不是空文件),那只是因为他对文件的检查方式不对。到底文件内容是否为空,不是“看”(指用显示文件内容的命令或者用编辑软件)它能不能显示出东西来,而是要通过查看文件的大小来获知。所谓的“看”,只能使用于文本文件,对非文本文件不适用。
3.&fwrite&函数使用二进制方式写文件。例如,一个整数如果用&4&个字节表示,则在文件中一个整数始终占有&4&个字节,不论整数的大小;与此不同,如果是用字符方式写文件,则一个整数在文件中占有的字节数与整数的大小(整型数字的个数)有关(当然还跟规定的格式有关,如果有的话)。
4.&对于二进制文件,它是用来被使用的(如读取、执行等),而不是用来看的(显示它的内容没有实际意义)。比如这个程序产生的二进制文件&datafile,它的作用就是用同样的结构体变量来读取,如上面的&jiutiao2004&&给出的程序所示例的那样;这也是检查楼主的程序写&datafile&是否成功的可靠方法。
5.&很多人也已经注意到了,写到&datafile&中的东西并不都是我们所需要的数据,其中还夹杂着一些“垃圾”。产生的原因是由于结构体的“位对齐”造成的(可参见以前的一些这方面的讨论,如这个帖子:http://bbs.chinaunix.net/forum/viewtopic.php?t=68019&highlight=%BD%E1%B9%B9%CC%E5)。本来结构体&record&的大小是&4+9&=&13&个字节,但是由于位对齐的原因,其实际大小是&16。另外,login&字符数组中的字符也并不是全部都是有效字符,这也是产生垃圾的一个原因。垃圾字符的存在不影响&datafile&的使用,不是错误。
6.&关于&fseek&函数。其功能是用来定位文件读写指针。如果文件指的是设备文件,则&fseek&的行为是不确定的;如果文件是一个磁盘文件,则&fseek&函数可以把文件指针指向文件结束符的后面。这时可以从这个位置起写数据,而这之前和原来文件结尾之间的“空隙”部分将用&0&来填充。因此,FH&的担心是多余的。他在上面是这样写的:
&;&;&【逻辑错误】看这里:
&;&;&for(i=4;i&;=0;i--)
&;&;&先用i=4调用putrec,对于空文件,fseek会怎样?
&;&;&fseek和fwrite的返回码都不判!
&;&;&对于空文件来说,最后写出的文件中应该包含几个记录,谁能说清楚?应该是3条记录而不是5条记录吧?
&;&;&是不是产生空洞好像和系统相关吧?&
所以对于空文件,象楼主那样使用fseek也不会有错误。另外,对于这个程序,即使对&fseek&和&fwrite&的返回值不作判断也是可以的,没有什么强有力的理由(比如算法上的要求,这一点要与&fread&函数区别)要求一定这么做,更谈不上是逻辑(算法)上的错误。
& 回复于: 21:09:58
to&whyglinux:
1.我没见过哪个文档里面说到fseek可以定位于文件逻辑结束之后的,如果有,麻烦向我推荐一下;如果没有,我不赞成这样使用,即使它被许多环境证明了。因为任何公司都不会保障未公开文档的功能的延续性。
2.关于fseek与fwrite的返回码问题,我仍坚持我的观点,至少可以从fseek的返回码判断是否成功定位于文件逻辑结束之后吧?此外,我觉得fwrite也应该判,至少我的程序里面都判,除非是写log的时候。
3.如果fseek并不能提供所特需的定位功能,那么这个程序是不是有逻辑上的错误呢?我是就此前提论事。
& 回复于: 07:41:23
引用:原帖由&"FH"&发表:to&whyglinux:
1.我没见过哪个文档里面说到fseek可以定位于文件逻辑结束之后的,如果有,麻烦向我推荐一下;如果没有,我不赞成这样使用,即使它被许多环境证明了。因为任何公司都不会保障未公开文档的功能的延续性..........
我查了下&APUE&中文版39页说过&lseek&这样做是可以的,fseek&没有说可以;可以的原因我估计fseek&&是对lseek&的上层封装.
其他同意你的观点.
有义务保证自己被调用的代码非常健壮,没有权力要求别人或调用的代码非常健壮.
基于上述的论调,不管是捕捉异常的办法或判断返回码,为了健壮性,程序的运行过程中检查错误是被要求的.
& 回复于: 09:19:14
to&windflowers1976:
我也觉得lseek可以的话fseek也应该可以。谢谢。
不过我在几个环境的man中都没有见到对此的说明。
& 回复于: 10:13:51
引用:原帖由&"FH"&发表:to&whyglinux:
1.我没见过哪个文档里面说到fseek可以定位于文件逻辑结束之后的,如果有,麻烦向我推荐一下;如果没有,我不赞成这样使用,即使它被许多环境证明了。因为任何公司都不会保障未公开文档的功能的延续性..........
这里有一篇SunOS的man明确提到了这一点:http://www.cs.biu.ac.il/cgi-bin/man?fseek+3C,还有这里:http://www.opengroup.org/onlinepubs//xsh/fseek.html。在一般的linux文档中好像是都没有此项说明,但是却能在这种情况下使用,说明还是支持fseek的越过文件尾部写数据的。
& 回复于: 10:36:47
引用:原帖由&"whyglinux"]&发表:
谢谢。
忽然想到VM好像就是这样写的,结果在Windows文件系统里留下很多碎片,都不能清理。
& 回复于: 10:52:41
碎片产生的原因应该是多次写文件造成的,与&fseek&是否越界(指文件尾部)使用无关。但是可能与&fseek&的频繁使用有关,因为&fseek&会刷新文件缓冲。其实不只是&fseek,还有很多途径可以造成频繁写文件的操作,这应该属于程序员的问题了。我是这么理解的。
& 回复于: 11:06:34
引用:原帖由&"whyglinux"]碎片产生的原因应该是多次写文件造成的,与&fseek&是否越界(指文件尾部)使用无关。&发表:
呵呵,不敢苟同。
我觉得这与其产生的缝隙有绝对的关系,Windows认为这就是碎片,不能移动。
顺便说一下,我用的是预分配空间方式。
& 回复于: 11:07:01
这个贴子讨论的人真多。
一个是fseek,一个是fwrite
|&设为精彩回复,大家继续,呵呵
& 回复于: 12:33:00
/*&Copyright&(C)&,&95,&96,&97&Free&Software&Foundation,&Inc.
&&&This&file&is&part&of&the&GNU&C&Library.
&&&The&GNU&C&Library&is&free&&you&can&redistribute&it&and/or
&&&modify&it&under&the&terms&of&the&GNU&Library&General&Public&License&as
&&&published&by&the&Free&Software&F&either&version&2&of&the
&&&License,&or&(at&your&option)&any&later&version.
&&&The&GNU&C&Library&is&distributed&in&the&hope&that&it&will&be&useful,
&&&but&WITHOUT&ANY&WARRANTY;&without&even&the&implied&warranty&of
&&&MERCHANTABILITY&or&FITNESS&FOR&A&PARTICULAR&PURPOSE.&&See&the&GNU
&&&Library&General&Public&License&for&more&details.
&&&You&should&have&received&a&copy&of&the&GNU&Library&General&Public
&&&License&along&with&the&GNU&C&L&see&the&file&COPYING.LIB.&&If&not,
&&&write&to&the&Free&Software&Foundation,&Inc.,&59&Temple&Place&-&Suite&330,
&&&Boston,&MA&,&USA.&&*/
#include&&errno.h&;
#include&&stdio.h&;
/*&Move&the&file&position&of&STREAM&to&OFFSET
&&&bytes&from&the&beginning&of&the&file&if&WHENCE
&&&is&SEEK_SET,&the&end&of&the&file&is&it&is&SEEK_END,
&&&or&the&current&position&if&it&is&SEEK_CUR.&&*/
int
fseek&(stream,&offset,&whence)
&&&&&register&FILE&*
&&&&&long&int&
&&&&&int&
{
&&long&int&o;
&&if&(!__validfp&(stream))
&&&&{
&&&&&&__set_errno&(EINVAL);
&&&&&&return&EOF;
&&&&}
&&/*&Write&out&any&pending&data.&&*/
&&if&(stream-&;__mode.__write&&&&__flshfp&(stream,&EOF)&==&EOF)
&&&&return&EOF;
&&/*&Make&sure&we&know&the&current&offset&info.&&*/
&&stream-&;__offset&=&-1;
&&if&(__stdio_check_offset&(stream)&==&EOF)
&&&&return&EOF;
&&/*&We&are&moving&the&file&position,&so&we&are&no&longer&at&EOF.&&*/
&&stream-&;__eof&=&0;
&&if&(stream-&;__pushed_back)
&&&&{
&&&&&&/*&Discard&the&character&pushed&back&by&ungetc.&&*/
&&&&&&stream-&;__bufp&=&stream-&;__pushback_
&&&&&&stream-&;__pushed_back&=&0;
&&&&}
&&/*&Check&the&WHENCE&argument&for&validity,&and&process&OFFSET
&&&&&into&an&absolute&position&in&O.&&By&the&end&of&this&switch,
&&&&&either&we&have&returned,&or&O&contains&an&absolute&position.&&*/
&&o&=&
&&switch&(whence)
&&&&{
&&&&default:
&&&&&&__set_errno&(EINVAL);
&&&&&&return&EOF;
&&&&case&SEEK_END:
&&&&&&/*&We&don't&know&where&the&end&of&the&file&is,
&so&seek&to&the&position&in&the&file&the&user&asked
&for,&and&then&look&where&that&is.&&*/
&&&&&&if&(stream-&;__io_funcs.__seek&==&NULL)
&&__set_errno&(ESPIPE);
&&return&EOF;
}
&&&&&&else
&&fpos_t&pos&=&(fpos_t)&o;
&&if&((*stream-&;__io_funcs.__seek)
&&&&&&(stream-&;__cookie,&&pos,&SEEK_END)&&&0)
&&&&&&if&(errno&==&ESPIPE)
stream-&;__io_funcs.__seek&=&NULL;
&&&&&&return&EOF;
&&stream-&;__offset&=&
&&/*&Make&O&be&absolute,&rather&than
&&&&&relative&to&the&end&of&the&file.&&*/
&&&&&&/*&Fall&through&to&try&an&absolute&seek.&&*/
&&&&case&SEEK_SET:
&&&&&&/*&Make&O&be&relative&to&the&buffer.&&*/
&&&&&&o&-=&stream-&;__
&&&&&&/*&Make&O&be&relative&to&the&current&position&in&the&buffer.&&*/
&&&&&&o&-=&stream-&;__bufp&-&stream-&;__
&&&&&&/*&Fall&through&to&see&if&we&can&do&it&by
&moving&the&pointer&around&in&the&buffer.&&*/
&&&&case&SEEK_CUR:
&&&&&&/*&If&the&offset&is&small&enough,&we&can&just
&move&the&pointer&around&in&the&buffer.&&*/
#if&0 /*&Why&did&I&think&this&would&ever&work???&&*/
&&&&&&if&(stream-&;__put_limit&&;&stream-&;__buffer)
&&/*&We&are&writing.&&*/
&&if&(stream-&;__bufp&+&o&&;=&stream-&;__buffer&&&
&&&&&&stream-&;__put_limit&&;&stream-&;__bufp&+&o&&&
&&&&&&stream-&;__get_limit&&;&stream-&;__bufp&+&o)
&&&&&&/*&We&have&read&all&the&data&we&will&change&soon.
&We&can&just&move&the&pointer&around.&&*/
&&&&&&stream-&;__bufp&+=&o;
&&&&&&return&0;
&&&&&&/*&Flush&the&buffer.&&*/
&&&&&&if&(__flshfp(stream,&EOF)&==&EOF)
return&EOF;
}&else
#endif
&&&&&&if&(o&&&0&?
&&(-o&&=&stream-&;__bufp&-&stream-&;__buffer)&:
&&(o&&=&stream-&;__get_limit&-&stream-&;__bufp))
&&stream-&;__bufp&+=&o;
&&return&0;
&&&&&&/*&Turn&it&into&an&absolute&seek.&&*/
&&&&&&o&+=&stream-&;__bufp&-&stream-&;__
&&&&&&o&+=&stream-&;__
&&&&&&
&&&&}
&&if&(o&&&0)
&&&&{
&&&&&&/*&Negative&file&position&is&meaningless.&&*/
&&&&&&__set_errno&(EINVAL);
&&&&&&return&-1;
&&&&}
&&/*&O&is&now&an&absolute&position,&the&new&target.&&*/
&&stream-&;__target&=&o;
&&/*&Set&bufp&and&both&end&pointers&to&the&beginning&of&the&buffer.
&&&&&The&next&i/o&will&force&a&call&to&the&input/output&room&function.&&*/
&&stream-&;__bufp
&&&&=&stream-&;__get_limit&=&stream-&;__put_limit&=&stream-&;__
&&/*&Make&sure&__flshfp&doesn't&think&the&put_limit&is&at&the&beginning
&&&&&of&the&buffer&because&of&line-buffering&magic.&&*/
&&stream-&;__linebuf_active&=&0;
&&/*&If&there&is&no&seek&function,&seeks&always&fail.&&*/
&&if&(stream-&;__io_funcs.__seek&==&NULL)
&&&&{
&&&&&&/*&This&is&preemptive,&since&we&don't&actually&do&the&seeking.
&But&it&makes&more&sense&for&fseek&to&to&fail&with&ESPIPE
&than&for&the&next&reading&or&writing&operation&to&fail
&that&way.&&*/
&&&&&&__set_errno&(ESPIPE);
&&&&&&return&EOF;
&&&&}
&&/*&Don't&actually&seek.&&The&next&reading&or&writing&operation
&&&&&will&force&a&call&to&the&input&or&output&room&function,
&&&&&which&will&move&to&the&target&file&position&before&reading&or&writing.&&*/
&&return&0;
}
& 回复于: 14:10:13
引用:原帖由&"FH"&发表:
呵呵,不敢苟同。
我觉得这与其产生的缝隙有绝对的关系,Windows认为这就是碎片,不能移动。
顺便说一下,我用的是预分配空间方式。
FH&多次提到“缝隙”这个概念,认为文件中真的存在着这么一个空白区域,真的是这样吗?
缝隙这个概念是在使用&fseek&定位文件指针、并且文件指针位置越过了文件结尾时产生的一个概念,此刻它指的是目前文件指针位置和原来文件结束位置之间的这片区域。注意,此时磁盘文件中并没有这样的一片区域,因为你还没有进行写文件的操作。
如果此时进行一个写文件的操作,根据&fseek&函数的说明,这块所谓的“缝隙”区域会用&0&来填充,然后随同要写的数据一起送到文件缓冲(即真正出现在文件中的内容)。从写文件开始起,“缝隙”这个概念已经不存在了,在磁盘文件中更不会有上述“缝隙”区域的存在。
为了说明这个问题,写了下面两个程序。程序功能分别是写一个100字节的文件(除了最后一个字节为字符&'a'&外,文件的其它内容为&0),区别就是一个不用&fseek,一个用fseek。特别请&FH&检验一下两种方式产生的两个文件有什么不同,fseek&带来的“缝隙”到底对最终文件有无影响。至少,我看不出这两个文件(tst1、tst2)有什么不同。
#include&&stdio.h&;
#if&1&//&&=&change&the&1&here&to&0&to&compile&program&2
//&program&1:&without&using&fseek()
int&main()
{
&&FILE&*
&&char&c[99];
&&int&i;
&&for&(i=0;&i&99;&i++)&{
&&&&c&=&0;
&&}
&&fp&=&fopen("tst1",&"w");
&&fwrite(c,&1,&99,&fp);
&&fwrite("a",&1,&1,&fp);
&&fclose(fp);
}
//&program&2:&with&using&fseek()
int&main()
{
&&FILE&*
&&fp&=&fopen("tst2",&"w");
&&fseek(fp,&100-1,&0);
&&fwrite("a",&1,&1,&fp);
&&fclose(fp);
}
#endif
fseek&函数的源代码
另外,上面windflowers1976贴出的&fseek&函数的源代码说明文件指针越过文件前面是非法的,但是指到文件结尾之后却没有问题。但是&fseek&的源代码还不能说明此时的&fwrite&或者&fread&函数是怎样处理这一情况的,关于这一点,要到&fwrite&和&fread&的代码中去查找吧。
& 回复于: 14:52:43
&/*&Don't&actually&seek.&&The&next&reading&or&writing&operation&
&&&&&will&force&a&call&to&the&input&or&output&room&function,&
&&&&&which&will&move&to&the&target&file&position&before&reading&or&writing.&&*/&
/*&Copyright&(C)&,&94,&96,&97,&98&Free&Software&Foundation,&Inc.
&&&This&file&is&part&of&the&GNU&C&Library.
&&&The&GNU&C&Library&is&free&&you&can&redistribute&it&and/or
&&&modify&it&under&the&terms&of&the&GNU&Library&General&Public&License&as
&&&published&by&the&Free&Software&F&either&version&2&of&the
&&&License,&or&(at&your&option)&any&later&version.
&&&The&GNU&C&Library&is&distributed&in&the&hope&that&it&will&be&useful,
&&&but&WITHOUT&ANY&WARRANTY;&without&even&the&implied&warranty&of
&&&MERCHANTABILITY&or&FITNESS&FOR&A&PARTICULAR&PURPOSE.&&See&the&GNU
&&&Library&General&Public&License&for&more&details.
&&&You&should&have&received&a&copy&of&the&GNU&Library&General&Public
&&&License&along&with&the&GNU&C&L&see&the&file&COPYING.LIB.&&If&not,
&&&write&to&the&Free&Software&Foundation,&Inc.,&59&Temple&Place&-&Suite&330,
&&&Boston,&MA&,&USA.&&*/
#include&&errno.h&;
#include&&stdio.h&;
#include&&string.h&;
/*&Write&NMEMB&chunks&of&SIZE&bytes&each&from&PTR&onto&STREAM.&&*/
size_t
fwrite&(ptr,&size,&nmemb,&stream)
&&&&&const&void&*
&&&&&size_t&
&&&&&size_t&
&&&&&register&FILE&*
{
&&register&const&unsigned&char&*p&=&(const&unsigned&char&*)&
&&register&size_t&to_write&=&size&*&
&&register&size_t&written&=&0;
&&int&
&&size_t&buffer_
&&int&default_
&&if&(!__validfp&(stream)&||&!stream-&;__mode.__write)
&&&&{
&&&&&&__set_errno&(EINVAL);
&&&&&&return&0;
&&&&}
&&if&(ferror&(stream))
&&&&return&0;
&&if&(p&==&NULL&||&to_write&==&0)
&&&&return&0;
&&if&(!stream-&;__seen&||&stream-&;__put_limit&==&stream-&;__buffer)
&&&&{
&&&&&&/*&This&stream&has&never&been&seen&before.
&Calling&__flshfp&will&give&it&a&buffer
&and&I/O&functions&if&it&needs&them.&&*/
&&&&&&if&(__flshfp&(stream,&*p++)&==&EOF)
return&0;
&&&&&&if&(--to_write&==&0)
return&1;
&&&&&&else
&&default_func
&&&&=&stream-&;__room_funcs.__output&==&__default_room_functions.__
&&{
&&&&int&save&=&
&&&&if&(__stdio_check_offset&(stream)&==&EOF&&&&errno&!=&ESPIPE)
&&&&&&{
stream-&;__error&=&1;
goto&
&&&&&&}
&&&&__set_errno&(save);
&&}
&&if&(stream-&;__buffer&==&NULL&&&&default_func&&&
&&&&&&stream-&;__offset&==&stream-&;__target)
&&write_through:
&&&&/*&This&is&an&unbuffered&stream&using&the&standard&output
&&&&&&&buffer-flushing&function,&so&we&just&do&a&straight&write.&&*/
&&&&{
&&&&&&int&count&=&(stream-&;__io_funcs.__write&==&NULL&?&to_write&:
&&&(*stream-&;__io_funcs.__write)&(stream-&;__cookie,
&&(const&char&*)&p,
&&to_write));
&&&&&&if&(count&&;&0)
&&written&+=&
&&if&(stream-&;__offset&!=&-1)
&&&&&&stream-&;__offset&+=&
&&&&&&stream-&;__target&=&stream-&;__
&&to_write&-=&
}
&&&&&&else
stream-&;__error&=&1;
&&&&&&goto&
&&&&}
&&/*&We&ignore&the&end&pointer&here&since&we&want&to&find&out&how&much&space
&&&&&is&really&in&the&buffer,&even&for&a&line-buffered&stream.&&*/
&&buffer_space&=&stream-&;__bufsize&-&(stream-&;__bufp&-&stream-&;__buffer);
&&newlinep&=&(stream-&;__linebuf&&&
&&&&&&memchr&((const&void&*)&p,&'\n',&to_write)&!=&NULL);
&&if&(newlinep&&&&stream-&;__bufp&==&stream-&;__buffer&&&
&&&&&&stream-&;__offset&==&stream-&;__target)
&&&&/*&The&buffer's&empty,&and&we&want&to&write&our&data
&&&&&&&out&soon&anyway,&so&just&write&it&straight&out.&&*/
&&&&goto&write_
&&if&(stream-&;__bufsize&==&0&&&&!default_func)
&&&&{
&&&&&&/*&No&buffer,&and&a&special&function.
&We&can't&do&much&better&than&putc.&&*/
&&&&&&while&(to_write--&&;&0)
&&if&(__flshfp&(stream,&*p++)&==&EOF)
}
&&&&}
&&else&if&(!default_func&||&buffer_space&&;=&to_write)
&&&&{
&&&&&&/*&There&is&enough&room&in&the&buffer&for&everything&we&want&to&write
&or&the&user&has&specified&his&own&output&buffer-flushing/expanding
&function.&&*/
&&&&fill_buffer:
&&&&&&while&(to_write&&;&0)
&&register&size_t&n&=&to_
&&if&(n&&;&buffer_space)
&&&&n&=&buffer_
&&buffer_space&-=&n;
&&written&+=&n;
&&to_write&-=&n;
&&if&(n&&&20)
&&&&while&(n--&&;&0)
&&&&&&*stream-&;__bufp++&=&*p++;
&&&&&&memcpy&((void&*)&stream-&;__bufp,&(void&*)&p,&n);
&&&&&&stream-&;__bufp&+=&n;
&&&&&&p&+=&n;
&&if&(to_write&==&0)
&&&&/*&Done&writing.&&*/
&&else&if&(buffer_space&==&0)
&&&&&&/*&We&have&filled&the&buffer,&so&flush&it.&&*/
&&&&&&if&(fflush&(stream)&==&EOF)
&&&&&&/*&Reset&our&record&of&the&space&available&in&the&buffer,
&since&we&have&just&flushed&it.&&*/
&&&&check_space:
&&&&&&buffer_space&=&(stream-&;__bufsize&-
&&&&&&(stream-&;__bufp&-&stream-&;__buffer));
&&&&&&if&(buffer_space&==&0)
&&/*&With&a&custom&output-room&function,&flushing&might
&&&&&not&create&any&buffer&space.&&Try&writing&a&single
&&&&&character&to&create&the&space.&&*/
&&if&(__flshfp&(stream,&*p++)&==&EOF)
&&goto&check_
&&&&&&/*&We&have&written&all&the&data&into&the&buffer.&&If&we&are
&line-buffered&and&just&put&a&newline&in&the&buffer,&flush&now&to
&make&sure&it&gets&out.&&*/
&&&&&&if&(newlinep)
fflush&(stream);
&&&&}
&&else
&&&&{
&&&&&&/*&It&won't&all&fit&in&the&buffer.&&*/
&&&&&&if&(stream-&;__bufp&!=&stream-&;__buffer)
&&/*&There&are&characters&in&the&buffer.&&Flush&them.&&*/
&&if&(__flshfp&(stream,&EOF)&==&EOF)
&&&&&&/*&The&buffer&has&been&flushed.
&Now&either&fill&it&or&write&directly.&&*/
&&&&&&buffer_space&=&stream-&;__bufsize&-&(stream-&;__bufp&-&stream-&;__buffer);
&&&&&&if&(stream-&;__offset&==&stream-&;__target&&&
&&(buffer_space&&&to_write&||&newlinep))
/*&What&we&have&to&write&is&bigger&than&the&buffer,
&&&or&it&contains&a&newline&and&we're&line-buffered,
&&&so&write&it&out.&&*/
goto&write_
&&&&&&else
/*&It&will&fit&in&the&buffer.&&*/
goto&fill_
&&&&}
&done:;
&&return&(size_t)&written&/&
}
weak_alias&(fwrite,&fwrite_unlocked)
呵呵,内核代码有人看啊.
& 回复于: 15:14:56
fseek允许设置文件位置超过文件的当前文件尾,如果之后在此新文件位置写入了数据,则后续从原文件尾新新写入的数据之间的空隙中读出的字节将用0填充直至次空隙写入实际的数据为止,下面给出的程序说明用fseek定位文件文件位置超过文件尾的两种情形。第一种是以非添加方式写数据超过文件尾,此时在当前文件尾和新写入的数据之间将行成所谓的“空洞”。第二种是以添加方式写数据,此时尽管可以用fseek定位文件当前位置超过文件尾,但是写该文件时,文件的当前位置被忽略,所有的数据都添加在文件尾并且文件当前位置被重新定位到新的文件尾
引用:
#include&&stdio.h&;
#include&&stdlib.h&;
#include&"err_exit.h"
char&buf[132];
int&main(int&argc,char&*argv[])
{
&&FILE&*
&&fpos_t&
&&if(argc&!=&2){
&&&&&fprintf(stderr,"Usage:&%s&mode&\n",argv[0]);
&&&&&exit(EXIT_FAILURE);
&&&}
&&&
&&&if(argv[1][0]!='a'){
&&&if&&((fd&=&fopen("test_file","w+"))==NULL)
&&&err_exit("fopen&failed");
&&&}
&&&else{
&&&&&if((fd&=&fopen("test_file","a+"))==NULL)
&&&&&err_exit("fopen&failed");
&&&&&}
&&&&&
&&&&&
&&&fputs("",fd);
&&&fputs("ABCDEFGHIJ",fd);
&&&
&&&fseek(fd,0,SEEK_END);
&&&fgetpos(fd,&pos);
&&&printf("current&file&en&position&is&%ld\n",pos);
&&&
&&&fseek(fd,30,SEEK_END);
&&&
&&&fgetpos(fd,&pos);
&&&printf("Now&we&call&fseek(fd,30,SEEK_END)\n");
&&&printf("Current&file&position&is&%ld&\n",pos);
&&&
&&&fputs("abcdefg",fd);
&&&printf("Now&we&write&%c&%s&%c\n",'\"',"abcdefg",'\"');
&&&
&&&fgetpos(fd,&pos);
&&&printf("current&position&of&file&end&is&%ld\n",pos);
&&&fclose(fd);
}
运行示例:
引用:#&t13&a+
current&file&en&position&is&20
Now&we&call&fseek(fd,30,SEEK_END)
Current&file&position&is&50&
Now&we&write&"&abcefg&"
current&position&of&file&end&is&57
[color=red]current&position&of&file&end&is&27[/color]
#&od&-c&test_file
0000000&&&0&&&1&&&2&&&3&&&4&&&5&&&6&&&7&&&8&&&9&&&A&&&B&&&C&&&D&&&E&&&F
0000020&&&G&&&H&&&I&&&J&&&a&&&b&&&c&&&d&&&e&&&f&&&g
[color=red]0000033[/color]
#&t13&w+
current&file&en&position&is&20
Now&we&call&fseek(fd,30,SEEK_END)
Current&file&position&is&50&
Now&we&write&"&abcefg&"
current&position&of&file&end&is&57
#&od&-c&test_file
0000000&&&0&&&1&&&2&&&3&&&4&&&5&&&6&&&7&&&8&&&9&&&A&&&B&&&C&&&D&&&E&&&F
0000020&&&G&&&H&&&I&&&J&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0
0000040&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0&&\0
0000060&&\0&&\0&&&a&&&b&&&c&&&d&&&e&&&f&&&g
0000071
几点说明:
&&&1。我这上面的程序基本上都是来源于unix程序设计教程这本书,自认为对于有一定c和c++编程基础又刚接触unix编程时的一本好书。当然如果在瘟下比较牛的话,可能也不需要,我是刚参加工作,理论有实践还比较差
&&&2。对于前面程序涉及的东西我想几位的解释已经让我明白的差不多了,先谢谢大家的热心帮助。
&&&3。关于大家后面的讨论我这里照样摘录了一个程序,大家运行测试一下,就知道里边包含的意思了
&&&4。对这个程序我运行的结果和书上给出的结果稍有出入,欢迎大家测试和讨论。
其中第一个红色行是对应行的书上给的结果
第二个红行是我运行出来的,书上没有。
& 回复于: 15:34:55
& 回复于: 18:00:06
to&whyglinux:
缝隙(gap)引自你提供的man文档。缝隙这一概念显然是逻辑上的而不是物理上的,这一点不用讨论。
我说的是缝隙给Windows&FAT32文件系统造成的假象,即文件碎片问题。
我的VMDK文件存在很多碎片,怎么copy都不能消除,也不能被碎片整理工具消除。
& 回复于: 18:12:23
那你看看文件的属性是否是系统属性,这样的文件不允许移动。比如Windows下那个大大的临时文件好像就是这样的。试试把文件的系统属性去掉,再用碎片整理。
原文链接:
转载请注明作者名及原文出处

我要回帖

更多关于 c struct 的文章

 

随机推荐