详解C语言fscanf函数读取文件教程及源码

目录
  • 第一部分:问题和结论
    • fscanf 函数的原型是:
  • 第二部分:实验代码
    • 实验代码:

fscanf 函数用于格式化读入文件中数据,可以大大提高读取文件的效率。这次笔者将最近使用该函数的一些经验记录下来。

第一部分:问题和结论

fscanf 函数的原型是:

int fscanf(FILE* stream, const char* format, [argument...]);

fscanf 函数与 scanf 函数用法类似,只不过前者用于读取文件流的数据而已。至于 fscanf 的基础用法我就不赘述了,网上的文章很多。简单提及一下要点:

  • 1. format str:如%d, %f, %c, %s等,分别表示读入一个整数,浮点数,字符,字符串。还可以加上控制,如%ld,表示读入一个长整型数,%20s表示最多读入20个字符。
  • 2. 返回值:在没有出错的情况下,fscanf 返回正确匹配和赋值的域的个数;如果出错,则返回EOF。

fscanf 的难点在于以下几点:

  • 1. 对空白符的处理(空格、制表符、换行符);
  • 2. *的用法;
  • 3. [] 以及 [^] 的用法;
  • 4. EOF 的处理;

对于上述问题,网上的文章都语焉不详,所以笔者自己写了点实验代码进行验证,应该是比较详细的小结了。
先把结论罗列在下面,具体的实验代码放在文章最后:

  • 1. 在空白符这个意义上来讲,fscanf 对空格、制表符、换行符是一视同仁的,不加区分的;%s会跳过前面的空白符,但是不会跳过后面的空白符;%c不会跳过空白符。
  • 2. *表示读取一个域,但是不赋值给变量。
  • 3. []表示只读取中括号内的字符,[]表示不读取中括号内的字符,值得注意的是%[]s将不会跳过前面的空白符。
  • 4. 如果还没有任何一个域匹配成功或者任何一个匹配失败发生之前,就达到了文件流末尾,就算出错;或者读取文件流出错。这两种情况下,fscanf 返回EOF。

第二部分:实验代码

为了验证上面提出的一些问题,笔者动手写了下面的实验代码进行验证分析,代码共分为六个部分,注意每个部分所使用的文件内容是不一样的:

  • 1. fscanf 对空格的处理;
  • 2. fscanf 对制表符的处理;
  • 3. fscanf 对换行符的处理;
  • 4. 当空格、制表符以及换行符混杂时fscanf的处理;
  • 5. []符号在format str中的应用;
  • 6. 出错的情况。

实验代码:

(注意为了清晰无误地表示出不同的空白符,用 <\b>代表空格,<\t>表示制表符,<\n>表示换行符。)

      #include <stdio.h>
      #include <errno.h>
      void fscanfTest(FILE* fp) {
        char c1, c2, s1[100], s2[100];
        int d;
        // 第一部分:fscanf对空格的处理
        printf("the content of file is:\n");
        printf("hello<\\b>world<\\b><\\b>666lucky<\\n>");
        printf("\n\n");
        // %s不会跳过后面的空格
        fscanf(fp, "%s", s1);
        printf("%s!\n", s1);  // hello!
        // %s会跳过前面的一个空格
        rewind(fp);   // 将光标移回文件开头
        fscanf(fp, "%s%s", s2, s1);
        printf("%s! %s!\n", s2, s1);  // hello! world!
        // %*s会从文件流中读入,但是不会将值赋予变量(*的作用)
        rewind(fp);
        fscanf(fp, "%*s%s", s1);
        printf("%s!\n", s1);  // world!
        // %s会跳过前面的多个空格
        rewind(fp);
        fscanf(fp, "%*s%s%s", s2, s1);
        printf("%s! %s!\n", s2, s1);  // world! 666lucky!
        // %c不会跳过空格
        rewind(fp);
        fscanf(fp, "%*s%c", &c1);
        printf("%c!\n", c1); // " !"
        // format str中的一个空格表示如果文件流接下来有连续空格,都跳过
        rewind(fp);
        fscanf(fp, "%*s%*s %c", &c1);
        printf("%c!\n", c1);          // "6!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d%c", &c1);
        printf("%c!\n", c1);          // "l!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d %c", &c2);   // 注意这里format str中的空格没起作用,是因为666和lucky之间没有空白符
        printf("%c!\n", c2);          // "l!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d%s", s1);
        printf("%s!\n", s1);          // "lucky!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d %s", s2);
        printf("%s!\n", s2);          // "lucky!"
        // format str中的多个连续空格和一个空格的效果是一样的
        rewind(fp);
        fscanf(fp, "%*s %c", &c1);
        printf("%c!\n", c1); // "w!"
        rewind(fp);
        fscanf(fp, "%*s  %c", &c2);
        printf("%c!\n", c2); // "w!"
        // 第二部分:fscanf对制表符的处理
        printf("the content of file is:\n");
        printf("hello<\\t>world<\\t><\\t>666lucky<\\n>");
        printf("\n\n");
        // %s不会跳过后面的制表符
        fscanf(fp, "%s", s1);
        printf("%s!\n", s1);  // hello!
        // %s会跳过前面的一个制表符
        rewind(fp);
        fscanf(fp, "%s%s", s2, s1);
        printf("%s! %s!\n", s2, s1);  // hello! world!
        // %s会跳过前面的多个制表符
        rewind(fp);
        fscanf(fp, "%*s%s%s", s2, s1);
        printf("%s! %s!\n", s2, s1);  // world! 666lucky!
        // %c不会跳过制表符
        rewind(fp);
        fscanf(fp, "%*s%c", &c1);
        printf("%c!\n", c1); // "<\\t>!"
        // format str中的一个制表符表示如果文件流接下来有连续制表符,都跳过
        rewind(fp);
        fscanf(fp, "%*s%*s\t%c", &c1);
        printf("%c!\n", c1);          // "6!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d%c", &c1);
        printf("%c!\n", c1);          // "l!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d\t%c", &c2);
        printf("%c!\n", c2);          // "l!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d%s", s1);
        printf("%s!\n", s1);          // "lucky!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d\t%s", s2);
        printf("%s!\n", s2);          // "lucky!"
        // format str中的多个连续制表符和一个制表符的效果是一样的
        rewind(fp);
        fscanf(fp, "%*s\t%c", &c1);
        printf("%c!\n", c1); // "w!"
        rewind(fp);
        fscanf(fp, "%*s\t\t%c", &c2);
        printf("%c!\n", c2); // "w!"
        // 第三部分:fscanf对换行符的处理
        printf("the content of file is:\n");
        printf("hello<\\n>world<\\n><\\n>666lucky<\\n>");
        printf("\n\n");
        // %s不会跳过后面的换行符
        fscanf(fp, "%s", s1);
        printf("%s!\n", s1);  // hello!
        // %s会跳过前面的一个换行符
        rewind(fp);
        fscanf(fp, "%s%s", s2, s1);
        printf("%s! %s!\n", s2, s1);  // hello! world!
        // %s会跳过前面的多个换行符
        rewind(fp);
        fscanf(fp, "%*s%s%s", s2, s1);
        printf("%s! %s!\n", s2, s1);  // world! 666lucky!
        // %c不会跳过换行符
        rewind(fp);
        fscanf(fp, "%*s%c", &c1);
        printf("%c!\n", c1); // "<\\n>!"
        // format str中的一个换行符表示如果文件流接下来有连续换行符,都跳过
        rewind(fp);
        fscanf(fp, "%*s%*s\n%c", &c1);
        printf("%c!\n", c1);          // "6!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d%c", &c1);
        printf("%c!\n", c1);          // "l!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d\n%c", &c2);
        printf("%c!\n", c2);          // "l!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d%s", s1);
        printf("%s!\n", s1);          // "lucky!"
        rewind(fp);
        fscanf(fp, "%*s%*s%*d\n%s", s2);
        printf("%s!\n", s2);          // "lucky!"
        // format str中的多个连续换行符和一个换行符的效果是一样的
        rewind(fp);
        fscanf(fp, "%*s\n%c", &c1);
        printf("%c!\n", c1); // "w!"
        rewind(fp);
        fscanf(fp, "%*s\n\n%c", &c2);
        printf("%c!\n", c2); // "w!"
        // 第四部分:当空格、制表符以及换行符混杂时fscanf的处理
        printf("the content of file is:\n");
        printf("hello<\\b><\\t><\\n>world<\\t><\\b><\\n>666lucky<\\n>");
        printf("\n\n");
        // %s会跳过连在一起的空格、制表符和换行符
        fscanf(fp, "%s%s", s2, s1);
        printf("%s! %s!\n", s2, s1);  // hello! world!
        // 当作为空白符时,format str中的空格、制表符以及换行符是一样的,可以相互替代!
        rewind(fp);
        fscanf(fp, "%*s %c", &c1);
        printf("%c!\n", c1);  // "w!"
        rewind(fp);
        fscanf(fp, "%*s\t%c", &c2);
        printf("%c!\n", c2);  // "w!"
        rewind(fp);
        fscanf(fp, "%*s\n%c", &c1);
        printf("%c!\n", c1);  // "w!"
        // 第五部分:[]符号在format str中的应用
        printf("the content of file is:\n");
        printf("hello<\\b><\\t><\\n>world<\\b><\\t>666lucky<\\n>");
        printf("\n\n");
        // [el]表示只读取'e'或者'l'这个字符,[0-9]表示只读取0-9这10个数字字符
        // %[]之后的域都不起作用了,不会读取文件流。
        // test#1: %c%[]s可以正常工作
        // output#1: h! ell!
        errno = 0;
        d = fscanf(fp, "%c%[el]s", &c1, s1);
        if (d == 2) printf("%c! %s!\n", c1, s1);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#2: %[]s后面的%c没有正常读取
        // output#2: d = 2
        errno = 0;
        rewind(fp);
        d = fscanf(fp, "%c%[el]s%c", &c2, s2, &c1);
        if (d == 3) printf("%c! %s! %c!\n", c2, s2, c1);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#3: %[]s后面的%s没有正常读取
        // output#3: d = 2
        errno = 0;
        rewind(fp);
        d = fscanf(fp, "%c%[el]s%s", &c1, s1, s2);
        if (d == 3) printf("%c! %s! %s!\n", c1, s1, s2);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#4: 再次运行fscanf函数就可以继续读取文件流
        // output#4: o! world!
        errno = 0;
        d = fscanf(fp, "%c%s", &c2, s2);
        if (d == 2) printf("%c! %s!\n", c2, s2);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // [^el]表示不读取'e'也不读取'l'这个字符,[^0-9]表示不读取0-9的数字字符
        // %[^]之后的域都不起作用了,不会读取文件流。
        // test#5: %c%[^]s可以正常工作,注意下面的%[^w]s这个域读取了空格、制表符以及换行符。
        // output#5: h! ello<\\b><\\t><\\n>!
        errno = 0;
        rewind(fp);
        d = fscanf(fp, "%c%[^w]s", &c1, s1);
        if (d == 2) printf("%c! %s!\n", c1, s1);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#6: %[^]s后面的%s没有正常读取
        // output#6: d = 2
        errno = 0;
        rewind(fp);
        d = fscanf(fp, "%c%[^w]s%s", &c2, s2, s1);
        if (d == 3) printf("%c! %s! %s!\n", c2, s2, s1);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#7: 再次运行fscanf函数就可以继续读取文件流
        // output#7: w! orld!
        errno = 0;
        d = fscanf(fp, "%c%s", &c1, s1);
        if (d == 2) printf("%c! %s!\n", c1, s1);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#8: %[^\n]s可以一直读取到行末尾,哪怕遇到空格或者制表符。
        // output#8: h! ello<\\b><\\t>!
        errno = 0;
        rewind(fp);
        d = fscanf(fp, "%c%[^\n]s", &c2, s2);
        if (d == 2) printf("%c! %s!\n", c2, s2);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#9: %[^ ]s不会读取空格,但是会读取制表符和换行符
        // output#9: <\\t><\\n>world!
        errno = 0;
        rewind(fp);
        d = fscanf(fp, "%*s%*c%[^ ]s", s1);
        if (d == 1) printf("%s!\n", s1);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#10: %[^\t]s不会读取制表符,但是会读取空格和换行符
        // output#10: <\\n>world<\\b>!
        errno = 0;
        rewind(fp);
        d = fscanf(fp, "%*s%*c%*c%[^\t]s", s2);
        if (d == 1) printf("%s!\n", s2);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#11: %[^]s不会跳过前面的空白符
        // output#11: <\\b><\\t><\\n>wo!
        errno = 0;
        rewind(fp);
        d = fscanf(fp, "%*s%[^r]s", s1);
        if (d == 1) printf("%s!\n", s1);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // 第六部分:出错的情况
        // 从第五部分 test#2 以及 test#3 的例子中可以看出,fscanf的返回值表示能够正确赋值的域的个数。如果出错,fscanf返回EOF。
        // 怎样才算出错?如果还没有任何一个域匹配成功或者任何一个匹配失败发生之前,就达到了文件流末尾,就算出错;或者读取文件流出错。就这两种情况。
        // 即使所有域都不匹配,但只要没到达文件流末尾并且读取文件流过程中没有发生错误,就不算出错,errno就是0。此时,fscanf返回0。
        printf("the content of file is:\n");
        printf("hello");
        printf("\n\n");
        // test#1: 此时的%c发生匹配失败,所以返回值为0。
        // output#1: d = 0
        errno = 0;
        d = fscanf(fp, "%*s%c", &c1);
        if (d == 1) printf("%c!\n", c1);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
        // test#2: 继续读取,已经到达文件流末尾,返回EOF。
        // output#2: d = -1
        errno = 0;
        d = fscanf(fp, "%c", &c2);
        if (d == 1) printf("%c!\n", c2);
        else {
          printf("d = %d\n", d);
          if (errno != 0) perror("fscanf");
          else printf("Error: no matching characters!\n");
        }
      }
      int main(int argc, char* argv[]) {
        FILE *fp;
        if (argc < 2) {
          printf("Usage: %s <filename>\n", argv[0]);
          return 1;
        }
        if ((fp = fopen(argv[1], "r")) == NULL) {
          printf("Error: cannot open file\n");
          return 1;
        }
        fscanfTest(fp);
        fclose(fp);
        return 0;
      }

以上就是详解C语言fscanf函数读取文件示例教程的详细内容,更多关于C语言fscanf读取文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言实现文件读写

    关于C语言的文件读写,我将介绍下面这几种方式: 字符的读写:使用 fgetc() 函数 和 fputc() 函数: 字符串的读写:使用 fgets() 函数和 fputs() 函数: 格式化的读写(主要用于文本文件):使用 fscanf() 函数和 fprintf() 函数. 字符读写: 1. fputc()函数 fputc(c,fp); //用于将一个字符写入文件 其中,fp为文件指针变量:c为要写入的字符,可以是字符常量或字符型变量.函数返回值:如果执行成功,返回写入的字符:否则,返回EOF

  • C语言中fgets和fscanf区别详解

    C语言中fgets和fscanf区别详解 一.作用上的大概区别: ①fgets:从文件中读取一行数据存入缓冲区(fgets遇到回车才会结束,不对空格和回车做任何转换就录入到缓冲区,结束后再往缓冲区写多一个\0,所以它是读一行数据) ②fscanf:从文件中读取一段数据存入缓冲区(fscanf遇到空格或回车就结束,它会把空格或回车转换为\0,所以它是读一小段数据) 二.举个例子:把a.txt文件中的内容复制到b.txt. a.txt中的内容(第一行中"我爱你小白"和"开玩笑&q

  • c语言 sscanf,scanf,fscanf正则表达式用法

    每种语言都对正则表达式有着不同程度的支持,在C语言中,有输入功能的这三个函数对正则表达式的支持并不强大,但是我们还是有必要了解一下. 首先来看看他们的原型: #include <stdio.h> int scanf(const char *format, ...); int fscanf(FILE *stream, const char *format, ...); int sscanf(const char *str, const char *format, ...); 均可以接受变参,ss

  • C语言中的fscanf()函数与vfscanf()函数使用

    C语言fscanf()函数:输入函数(比较常用) 头文件: #include <stdio.h> 定义函数: int fscanf(FILE * stream, const char *format, ...); 函数说明:fscanf()会自参数stream 的文件流中读取字符串, 再根据参数format 字符串来转换并格式化数据.格式转换形式请参考scanf(). 转换后的结构存于对应的参数内. 返回值:成功则返回参数数目, 失败则返回-1, 错误原因存于errno 中. 范例 #incl

  • C语言fprintf()函数和fscanf()函数的具体使用

    目录 fprintf()函数 fscanf()函数 fprintf()函数   在C语言中常用使用的打印函数是printf()函数,这个多用于给控制台打印数据,如果需要将内容直接打印到某个文件中的时候,可以使用fprintf()函数.它有两个参数,第一个参数为待写入的文件指针,第二个参数为待写入的内容.下面通过一个简单的例子来演示它的用法. int main() { FILE *in,*out; int ret; char ch; /* 打开文件 */ in = fopen("123.txt&q

  • 详解C语言fscanf函数读取文件教程及源码

    目录 第一部分:问题和结论 fscanf 函数的原型是: 第二部分:实验代码 实验代码: fscanf 函数用于格式化读入文件中数据,可以大大提高读取文件的效率.这次笔者将最近使用该函数的一些经验记录下来. 第一部分:问题和结论 fscanf 函数的原型是: int fscanf(FILE* stream, const char* format, [argument...]); fscanf 函数与 scanf 函数用法类似,只不过前者用于读取文件流的数据而已.至于 fscanf 的基础用法我就

  • 详解Android开发数据持久化之文件存储(附源码)

    其实我们在社交网络上面所发出的任何信息, 都希望能够保留下来. 那么如何实现呢? 数据持久化 数据持久化, 就是将内存中的瞬时数据保存在存储设备中, 保证即便关机之后, 数据仍然存在. 保存在内存中的数据是瞬时数据, 保存在存储设备中的数据就是处于持久状态的. 持久化技术则是提供了一种机制可以让数据在瞬时状态和持久状态之间进行转换, Android系统中主要提供了3种方式用于简单地实现数据持久化功能, 即文件存储, SharePreference存储, 以及数据库存储. 当然你也可以将数据保存在

  • 详解C语言gets()函数与它的替代者fgets()函数

    在c语言中读取字符串有多种方法,比如scanf() 配合%s使用,但是这种方法只能获取一个单词,即遇到空格等空字符就会返回.如果要读取一行字符串,比如: I love BIT 这种情况,scanf()就无能为力了.这时我们最先想到的是用gets()读取. gets()函数从标准输入(键盘)读入一行数据,所谓读取一行,就是遇到换行符就返回.gets()函数并不读取换行符'\n',它会吧换行符替换成空字符'\0',作为c语言字符串结束的标志. gets()函数经常和puts()函数配对使用,puts

  • 详解C 语言项目中.h文件和.c文件的关系

    详解C 语言项目中.h文件和.c文件的关系 在编译器只认识.c(.cpp))文件,而不知道.h是何物的年代,那时的人们写了很多的.c(.cpp)文件,渐渐地,人们发现在很多.c(.cpp)文件中的声明语句就是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每个.c(.cpp)文件.但更为恐怖的是,当其中一个声明有变更时,就需要检查所有的.c(.cpp)文件. 于是人们将重复的部分提取出来,放在一个新文件里,然后在需要的.c(.cpp)文件中敲入#include XXXX这样的语句.这样即

  • 详解C语言sscanf()函数、vsscanf()函数、vscanf()函数

    C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: #include <stdio.h> sscanf()函数用于从字符串中读取指定格式的数据,其原型如下: int sscanf (char *str, char * format [, argument, ...]); [参数]参数str为要读取数据的字符串:format为用户指定的格式:argument为变量,用来保存读取到的数据. [返回值]成功则返回参数数目,失败则返回-1,错误原因存于errno 中. sscanf()

  • 详解C语言之函数

    目录 函数的调用 函数调用方式 函数嵌套调用 递归调用 内部函数与外部函数 内部函数 外部函数 局部变量与全局变量 局部变量 全局变量 总结 函数的调用 函数调用方式 函数语句调用 函数表达式调用 函数参数调用 sum(); //函数语句调用 result = average * sum(a); //函数表达式调用 此时函数名出现在表达式中,其返回值将作为表达式的算数参与计算. result = sum(sum1(a)); //函数参数调用 此时函数名出现在另一个函数的参数中,其返回值将作为实参

  • 实例详解易语言返回函数

    返回()是易语言的重要函数,很多函数都有返回值,就是用这个函数返回. 非无私奉献,拒绝看经验不回复,学懂了记得按照下面做: 具体操作请看图. 1.易语言新建一个windows窗口 点击进入代码编辑区 2.我们首先定义一个变量a 整数型 3.然后我们输入计次循环首 这个具体用法请看 易语言计次循环首函数实例讲解 4.我们在循环里输入函数 如果真(a>5) 这个具体用法请看 易语言如果真函数用法 5.然后我们在最后位置输入 调试输出(1) 运行结果为1 6.我们在如果真下面输入 返回() 发现没有结

  • 详解R语言plot函数参数合集

    最近用R语言画图,plot 函数是用的最多的函数,而他的参数非常繁多,由此总结一下,以供后续方便查阅. plot(x, y = NULL, type = "p", xlim = NULL, ylim = NULL, log = "", main = NULL, sub = NULL, xlab = NULL, ylab = NULL, ann = par("ann"), axes = TRUE, frame.plot = axes, panel.

  • 详解Vue3中setup函数的使用教程

    目录 vue2 和 vue3 开发的区别 使用 setup 原因 setup 用法 setup 可以接受哪些参数 setup 详解 setup 函数自动执行 setup 函数定义变量 setup 创建方法 动态更新数据 vue2 和 vue3 开发的区别 首先,目前来说 vue3 发布已经有一段时间了,但是呢,由于还处于优化完善阶段,对于 vue3 开发项目的需求不是很高,主要还是以 vue2 开发为主,但是相信,vue3 进行项目开发是大势所趋. vue2 开发项目过程中,会存在代码冗余和结构

  • 详解Python中open()函数指定文件打开方式的用法

    文件打开方式 当我们用open()函数去打开文件的时候,有好几种打开的模式. 'r'->只读 'w'->只写,文件已存在则清空,不存在则创建. 'a'->追加,写到文件末尾 'b'->二进制模式,比如打开图像.音频.word文件. '+'->更新(可读可写) 这个带'+'号的有点难以理解,上代码感受下. with open('foo.txt', 'w+') as f: f.write('bar\n') f.seek(0) data = f.read() 可以看到,上面这段代码

随机推荐