首页 > 代码库 > 文件操作方法fscanf

文件操作方法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