文件操作方法fscanf
直入主题,首先把经典方法放在前面:
如下情况大量有规律的数据存储在文件中格式化的读取方法:
Almond #EED9C4
Antique Brass #C88A65
Apricot #FDD5B1
Aquamarine #71D9E2
Asparagus #7BA05B
.............................
先上代码:
1 FILE *fp; //定义文件指针
2 char a[20]={0}; //定义两个数组来接受数据 3 char b[20]={0}; 4 5 fp=fopen("/Users/My/file","r"); //打开文件 6 if(fp==NULL) 7 { 8 printf("open the file is error!\n"); 9 exit(0); 10 } 11 fseek(fp,0,SEEK_SET); //获取文件内部指针 12 13 15 while(2==fscanf(fp,"%[^#]%s\n",a,b)) //使用fscanf函数格式化读取文件里的数据,使用#号作为分隔符 16 { 17 printf("a=%s--------\nb=%s\n",a,b); 18 // printf("sizea=%ld\n",sizeof(a)); 19 // NSLog(@"astring=%@",[NSString stringWithFormat:@"%s",a]); 20 } 21 22 fclose(fp); //关闭文件
读取结果:
a=Shadow, b=#837050
a=Shamrock, b=#33CC99
a=Shocking,Pink, b=#FF6FFF
a=Silver b=#C9C0BB
a=Sky Blue b=#76D7EA
a=Spring Green b=#ECEBBD
a=Sunglow b=#FFCC33
a=Sunset Orange b=#FE4C4
解释:
这里使用的C语言提供的一种格式化读取方法,非常像 正则表达式 的读取方式,"%[^#]%s\n"这里的含义就是以#为分隔符读取数据,把数据分为两部分,\n表示读到换行符为止.使用while循环可以读取一个完整的文件直到结束.
所以在最后用a,b可以分别接收到#号前后的数据并存入其中,每次只读取一行.
特别注意:
如果把上边的 %[^#]%s\n 替换为"%[^#]#%s\n"得到的结果如下:
a=Shadow, b=837050
a=Shamrock, b=33CC99
a=Shocking,Pink, b=FF6FFF
a=Silver b=C9C0BB
a=Sky Blue b=76D7EA
a=Spring Green b=ECEBBD
a=Sunglow b=FFCC33
a=Sunset Orange b=FE4C40
再如果替换为 %[^#] %[#^]\n结果会发生如下错误:
a=Shadow, b=#
a=837050
Shamrock, b=#
a=33CC99
Shocking,Pink, b=#
替换为"%[^#]%[#83^]\n"结果如下:
a=Shadow, b=#83
a=050
Shamrock, b=#33
a=C99
Shocking,Pink, b=#
a=F6FFF
Silver b=#
a=9C0BB
Sky Blue b=#
a=6D7EA
Spring Green b=#
(上边这个有点不懂,不仅只按尽可能匹配的截取方式截取,而且文件指针的位置还跳过一个
b=#83
a=050
) 原来是#837050,但是他的结果把7给跳过了,Why???????????????????????????????????????????????
再次替换为 "%[^#]%[^]\n" 或者%[^#]%[^\n]结果如下:
a=Shadow, b=#837050
a=
Shamrock, b=#33CC99
a=
Shocking,Pink, b=#FF6FFF
a=
Silver b=#C9C0BB
a=
Sky Blue b=#76D7EA
a=
Spring Green b=#ECEBBD
a=
Sunglow b=#FFCC33
我们发现此时从第二次开始,每次先读取了一个换行符\n,此时可以认为从第一次读取介绍后,文件内部指针每次都以\n为介绍标识,停留在了\n上,所以每次第一个读取的先是换行符\n,所以造成了上述结果.(只是猜测没有具体测试,这几种变化我也不太懂).
后来补充:上面的猜测现在已经证实是正确的了,当把while改为如下:
while(2==fscanf(fp,"%[^#]%[^]\n",a,b))
{
fseek(fp, ftell(fp)+1, SEEK_SET);
printf("a=%s b=%s\n",a,b);
}
发现结果如下:
a=Shadow, b=#837050
a=Shamrock, b=#33CC99
a=Shocking,Pink, b=#FF6FFF
a=Silver b=#C9C0BB
a=Sky Blue b=#76D7EA
总结: "%[^#]%s\n 和"%[^#]%[^]\n或者%[^#]%[^\n]的区别:
前者%s\n是读取到\n的下一个位置,后者%[^]\n或者%[^#]%[^\n]是读取到\n止.
%[^#]%s\n, %[^#]#%s\n, %[^#] %[#XXX^]\n的区别:
%[^#]%s\n:以#号为分割符,前一个读取到#号为止(不包含#号),后一个字符读完到\n的下一个指针位置.
%[^#]#%s\n: %[^#]是读取到#的前一个位置为止(不包含#), #%s 从#的后一个位置开始读取(不包括#),读取到\n的下一个位置
%[^#] %[#XXX^]\n: %[#XXX^]尽最大可能的匹配#XXX读取(包含#),最大匹配后读取结束.如" %[#1232^] 遇到 #1525 读出结果为:#1
对上面不太理解??没关系再来个类似的例子,我也加深下学习!
文件中有如下数据:
4,5,41,w,20.585828
4,6,51,r,52.012547
........................
FILE *fp; int fd; long dev; long offset; long length; char ch; double ts=0.000000; fp=fopen("/Users/My/file.save","r"); if(fp==NULL) { printf("open the file is error!\n"); exit(0); } lseek(fd,0,SEEK_SET); //具体解释:fscanf(fp,"%ld,%ld,%ld,%c,%lf\n",&dev,&offset,&length,&ch,&ts)
// 亲,这里的 %ld,%ld,%ld,%c,%lf\n 可不是像下面printf里字符串含义. 这里的逗号(',')代表的是以逗号(',')为分 // 隔符(或称为分割单位),以此作为分割数据的依据,因此逗号必不可少,换行符\n则是解析完一行数据的依据.
// 所以说上面的逗号','和'\n'都是必不可少的,否则会造成程序错误,读取失败(多多理解)
while(5==fscanf(fp,"%ld,%ld,%ld,%c,%lf\n",&dev,&offset,&length,&ch,&ts))
{
// 这里的逗号','和'\n'是来规范输出后的格式,可以省略,但是fscanf中得绝对不可以省略.
printf("%ld,%ld,%ld,%c,%lf\n",dev,offset,length,ch,ts);
}
fclose(fp);
再举一例: 这个例子很好的说明了fscanf是如何格式化读取文件的
long l;
float fp;
char s[81];
char c;
stream=fopen("/Users/lanou3g/fscanf.out","w+");
if(stream==NULL)
printf("Thefilefscanf.outwasnotopened\n");
else
{
fprintf(stream,"%s,%d,%f,%c","a-string",
65000,3.14159,'x'); // 这个是格式化写入文件,和fscanf是相反的操作,字符串的具体意义和fscanf相似,他们俩配合的相当完美
/*Setpointertobeginningoffile:*/
fseek(stream,0L,SEEK_SET);
/*Readdatabackfromfile:*/
fscanf(stream,"%[^,]",s); // 注意这里字符串的格式化读取时的格式是%[^,] 说明读取的是字符串且用逗号分割,这个和第一个例子中 %[^#]%s\n的用法很相似, %[^#]%s\n的意思是读取#号分割的前后字符串,第一个字符串必须是格式化的%[^#]以便和后边的字符串做区分,第二个由于后面读到行尾所以可以直接写%s [特别注意的时%s#%s\n的写法和 %[^#]%[^]的写法是错误的,具体原因我也还不太清楚].
fscanf(stream,",%ld",&l); //下面几个数据都是用",格式符"作为格式化输出标准, "%ld,"这种逗号放后面的写法是错误的.
fscanf(stream,",%f",&fp);
fscanf(stream,",%c",&c);
/*Outputdataread:*/
printf("%s\n",s);
printf("%ld\n",l);
printf("%f\n",fp);
printf("%c\n",c);
fclose(stream);
}
如果把上面的例子中 fscanf(stream,"%[^,]",s);改为fscanf(stream,"%s,",s);读取结果发生错误如下:
a-string,65000,3.141590,x
0
0.000000