本文最后更新于 97 天前,其中的信息可能已经过时,如有错误请发送邮件到 shikeAB@outlook.com。
- 行是文本编辑器中的概念,文件流中就是一个字符。这个在不同的平台是有差异的。window 平台 ‘\r\n’,linux 平台是’\n’
- 平台差异
- windows 平台在写入’\n’是会体现为’\r\n’,linux 平台在写入’\n’时会体现为’\n’。windows 平台在读入’\r\n’时,体现为一个字符’\n’,linux 平台在读入’\n’时,体现为一个字符’\n’
- linux 读 windows 中的换行,则会多读一个字符,windows 读 linux 中的换行,则没有问题
| #include |
| |
| int main() |
| { |
| FILE *fw = fopen("test.txt", "w+"); |
| fputc('a', fw); |
| fputc('\n', fw); |
| fputc('b', fw); |
| fclose(fw); |
| return 0; |
| } |
| |
函数声明 |
int fputs(char *str,FILE *fp) |
所在文件 |
stdio.h |
函数功能 |
把 str 指向的字符串写入 fp 指向的文件中。 |
参数及返回解析 |
|
参数 |
char * str : 表示指向的字符串的指针。 |
参数 |
FILE *fp : 指向文件流结构的指针。 |
返回值 |
int 正常,返 0;出错返 EOF。 |
| #include |
| |
| int main() |
| { |
| FILE *fw = fopen("test.txt", "w+"); |
| |
| fputs("lnj\n", fw); |
| fputs("it666\n", fw); |
| fclose(fw); |
| return 0; |
| } |
| |
| #include |
| |
| int main() |
| { |
| FILE *fp = fopen("test.txt", "w+"); |
| |
| fputs("lnj\0it666\n", fp); |
| |
| fclose(fp); |
| return 0; |
| } |
| |
函数声明 |
char *fgets(char *str,int length,FILE *fp) |
所在文件 |
stdio.h |
函数功能 |
从 fp 所指向的文件中,至多读 length-1 个字符,送入字符数组 str 中, 如果在读入 length-1 个字符结束前遇 \n 或 EOF,读入即结束,字符串读入后在最后加一个‘\0’字符。 |
参数及返回解析 |
|
参数 |
char * str : 指向需要读入数据的缓冲区。 |
参数 |
int length : 每一次读数字符的字数。 |
参数 |
FILE* fp : 文件流指针。 |
返回值 |
char * 正常,返 str 指针;出错或遇到文件结尾 返空指针 NULL。 |
| #include |
| |
| int main() |
| { |
| FILE *fp = fopen("test.txt", "w+"); |
| |
| fputs("it666\n", fp); |
| |
| |
| |
| rewind(fp); |
| char str[1024]; |
| |
| |
| fgets(str, 4, fp); |
| |
| printf("str = %s", str); |
| fclose(fp); |
| return 0; |
| } |
| |
| #include |
| int main() |
| { |
| FILE *fp = fopen("test.txt", "w+"); |
| |
| fputs("lnj\n", fp); |
| fputs("it666\n", fp); |
| |
| |
| |
| rewind(fp); |
| char str[1024]; |
| |
| |
| |
| fgets(str, 1024, fp); |
| |
| printf("str = %s", str); |
| fclose(fp); |
| return 0; |
| } |
| |
| #include |
| |
| int main() |
| { |
| FILE *fp = fopen("test.txt", "w+"); |
| |
| fputs("lnj\n", fp); |
| fputs("it666", fp); |
| |
| |
| |
| rewind(fp); |
| char str[1024]; |
| |
| |
| while(fgets(str, 1024, fp)){ |
| printf("str = %s", str); |
| } |
| fclose(fp); |
| return 0; |
| } |
| |
- 注意点:
- 企业开发中能不用 feof 函数就不用 feof 函数
- 如果最后一行,没有行‘\n’的话则少读一行
| #include |
| |
| int main() |
| { |
| FILE *fp = fopen("test.txt", "w+"); |
| |
| fputs("12345678910\n", fp); |
| fputs("12345678910\n", fp); |
| fputs("12345678910", fp); |
| |
| |
| |
| rewind(fp); |
| char str[1024]; |
| |
| |
| while(fgets(str, 1024, fp) && !feof(fp)){ |
| printf("str = %s", str); |
| } |
| fclose(fp); |
| return 0; |
| } |
| |
- 作业:
- 利用 fgets (str, 5, fp) 读取下列文本会读取多少次?
- C 语言己经从接口的层面区分了,文本的读写方式和二进制的读写方式。前面我们讲的是文本的读写方式。
- 所有的文件接口函数,要么以 ‘\0’,表示输入结束,要么以 ‘\n’, EOF (0xFF) 表示读取结束。 ‘\0’ ‘\n’ 等都是文本文件的重要标识,而所有的二进制接口对于这些标识,是不敏感的。
+ 二进制的接口可以读文本,而文本的接口不可以读二进制
函数声明 |
int fwrite(void *buffer, int num_bytes, int count, FILE *fp) |
所在文件 |
stdio.h |
函数功能 |
把 buffer 指向的数据写入 fp 指向的文件中 |
参数 |
char * buffer : 指向要写入数据存储区的首地址的指针 |
|
int num_bytes: 每个要写的字段的字节数 count |
|
int count : 要写的字段的个数 |
|
FILE* fp : 要写的文件指针 |
返回值 |
int 成功,返回写的字段数;出错或文件结束,返回 0。 |
| #include |
| #include |
| |
| int main() |
| { |
| FILE *fp = fopen("test.txt", "wb+"); |
| |
| char *str = "lnj\0it666"; |
| |
| |
| |
| |
| |
| |
| fwrite((void *)str, 9, 1, fp); |
| |
| fclose(fp); |
| return 0; |
| } |
| |
函数声明 |
int fread(void *buffer, int num_bytes, int count, FILE *fp) |
所在文件 |
stdio.h |
函数功能 |
把 fp 指向的文件中的数据读到 buffer 中。 |
参数 |
char * buffer : 指向要读入数据存储区的首地址的指针 |
|
int num_bytes: 每个要读的字段的字节数 count |
|
int count : 要读的字段的个数 |
|
FILE* fp : 要读的文件指针 |
返回值 |
int 成功,返回读的字段数;出错或文件结束,返回 0。 |
| #include |
| |
| int main() |
| { |
| |
| FILE *fr = fopen("test.txt", "rb+"); |
| char buf[1024] = {0}; |
| |
| |
| |
| |
| |
| |
| |
| int n = fread(buf, 1, 1024, fr); |
| printf("%i\n", n); |
| for(int i = 0; i < n; i++){ |
| printf("%c", buf[i]); |
| } |
| fclose(fr); |
| return 0; |
| } |
| |
- 注意点:
- 读取时 num_bytes 应该填写读取数据类型的最小单位,而 count 可以随意写
- 如果读取时 num_bytes 不是读取数据类型最小单位,会引发读取失败
- 例如:存储的是 char 类型 6C 6E 6A 00 69 74 36 36 36
如果 num_bytes 等于 1, count 等于 1024, 那么依次取出 6C 6E 6A 00 69 74 36 36 36 , 直到取不到为止
如果 num_bytes 等于 4, count 等于 1024, 那么依次取出 [6C 6E 6A 00][69 74 36 36] , 但是最后还剩下一个 36, 但又不满足 4 个字节,那么最后一个 36 则取不到
| |
| |
| |
| int main() |
| { |
| |
| // test.txt中存放的是"lnj\0it666" |
| FILE *fr = fopen("test.txt", "rb+"); |
| char buf[1024] = {0}; |
| /* |
| while(fread(buf, 4, 1, fr) > 0){ |
| printf("%c\n", buf[0]); |
| printf("%c\n", buf[1]); |
| printf("%c\n", buf[2]); |
| printf("%c\n", buf[3]); |
| } |
| */ |
| /* |
| while(fread(buf, 1, 4, fr) > 0){ |
| printf("%c\n", buf[0]); |
| printf("%c\n", buf[1]); |
| printf("%c\n", buf[2]); |
| printf("%c\n", buf[3]); |
| } |
| */ |
| while(fread(buf, 1, 1, fr) > 0){ |
| printf("%c\n", buf[0]); |
| } |
| fclose(fr); |
| return 0; |
| } |
| |
- 注意: fwrite 和 fread 本质是用来操作二进制的
- 所以下面用法才是它们的正确打开姿势
| #include |
| |
| int main() |
| { |
| |
| FILE *fp = fopen("test.txt", "wb+"); |
| int ages[4] = {1, 3, 5, 6}; |
| fwrite(ages, sizeof(ages), 1, fp); |
| rewind(fp); |
| int data; |
| while(fread(&data, sizeof(int), 1, fp) > 0){ |
| printf("data = %i\n", data); |
| } |
| return 0; |
| } |
| |
- 结构体中的数据类型不统一,此时最适合用二进制的方式进行读写
- 读写单个结构体
| #include |
| |
| typedef struct{ |
| char *name; |
| int age; |
| double height; |
| } Person; |
| |
| int main() |
| { |
| Person p1 = {"lnj", 35, 1.88}; |
| |
| |
| |
| |
| FILE *fp = fopen("person.stu", "wb+"); |
| fwrite(&p1, sizeof(p1), 1, fp); |
| |
| rewind(fp); |
| Person p2; |
| fread(&p2, sizeof(p2), 1, fp); |
| printf("name = %s\n", p2.name); |
| printf("age = %i\n", p2.age); |
| printf("height = %lf\n", p2.height); |
| |
| return 0; |
| } |
| |
| #include |
| |
| typedef struct{ |
| char *name; |
| int age; |
| double height; |
| } Person; |
| |
| int main() |
| { |
| Person ps[] = { |
| {"zs", 18, 1.65}, |
| {"ls", 21, 1.88}, |
| {"ww", 33, 1.9} |
| }; |
| |
| |
| FILE *fp = fopen("person.stu", "wb+"); |
| fwrite(&ps, sizeof(ps), 1, fp); |
| |
| rewind(fp); |
| Person p; |
| while(fread(&p, sizeof(p), 1, fp) > 0){ |
| printf("name = %s\n", p.name); |
| printf("age = %i\n", p.age); |
| printf("height = %lf\n", p.height); |
| } |
| return 0; |
| } |
| |
| #include |
| #include |
| |
| typedef struct person{ |
| char *name; |
| int age; |
| double height; |
| struct person* next; |
| } Person; |
| Person *createEmpty(); |
| void insertNode(Person *head, char *name, int age, double height); |
| void printfList(Person *head); |
| int saveList(Person *head, char *name); |
| Person *loadList(char *name); |
| |
| int main() |
| { |
| |
| |
| |
| |
| |
| |
| |
| Person *head = loadList("person.list"); |
| printfList(head); |
| return 0; |
| } |
| |
| |
| |
| |
| |
| |
| Person *loadList(char *name){ |
| |
| FILE *fp = fopen(name, "rb+"); |
| if(fp == NULL){ |
| return NULL; |
| } |
| |
| Person *head = createEmpty(); |
| |
| Person *node = (Person *)malloc(sizeof(Person)); |
| while(fread(node, sizeof(Person), 1, fp) > 0){ |
| |
| |
| node->next = head->next; |
| |
| head->next = node; |
| |
| |
| node = (Person *)malloc(sizeof(Person)); |
| } |
| |
| free(node); |
| fclose(fp); |
| return head; |
| } |
| |
| |
| |
| |
| |
| |
| |
| int saveList(Person *head, char *name){ |
| |
| FILE *fp = fopen(name, "wb+"); |
| if(fp == NULL){ |
| return -1; |
| } |
| |
| Person *cur = head->next; |
| |
| while(cur != NULL){ |
| fwrite(cur, sizeof(Person), 1, fp); |
| cur = cur->next; |
| } |
| fclose(fp); |
| return 0; |
| } |
| |
| |
| |
| |
| void printfList(Person *head){ |
| |
| Person *cur = head->next; |
| |
| while(cur != NULL){ |
| |
| printf("name = %s\n", cur->name); |
| printf("age = %i\n", cur->age); |
| printf("height = %lf\n", cur->height); |
| printf("next = %x\n", cur->next); |
| printf("-----------\n"); |
| |
| cur = cur->next; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| void insertNode(Person *head, char *name, int age, double height){ |
| |
| Person *node = (Person *)malloc(sizeof(Person)); |
| |
| node->name = name; |
| node->age = age; |
| node->height = height; |
| |
| |
| |
| node->next = head->next; |
| |
| head->next = node; |
| } |
| |
| |
| |
| |
| Person *createEmpty(){ |
| |
| Person *head = NULL; |
| |
| head = (Person *)malloc(sizeof(Person)); |
| if(head == NULL){ |
| return head; |
| } |
| head->next = NULL; |
| |
| return head; |
| } |
| |
函数声明 |
long ftell ( FILE * stream ); |
所在文件 |
stdio.h |
函数功能 |
得到流式文件的当前读写位置,其返回值是当前读写位置偏离文件头部的字节数. |
参数及返回解析 |
|
参数 |
FILE * 流文件句柄 |
返回值 |
int 成功,返回当前读写位置偏离文件头部的字节数。失败, 返回 - 1 |
| #include |
| |
| int main() |
| { |
| char *str = "123456789"; |
| FILE *fp = fopen("test.txt", "w+"); |
| long cp = ftell(fp); |
| printf("cp = %li\n", cp); |
| |
| fputc(str[0], fp); |
| cp = ftell(fp); |
| printf("cp = %li\n", cp); |
| fclose(fp); |
| return 0; |
| } |
| |
函数声明 |
void rewind ( FILE * stream ); |
所在文件 |
stdio.h |
函数功能 将文件指针重新指向一个流的开头。 |
|
参数及返回解析 |
|
参数 |
FILE * 流文件句柄 |
返回值 |
void 无返回值 |
| #include |
| |
| int main() |
| { |
| char *str = "123456789"; |
| FILE *fp = fopen("test.txt", "w+"); |
| long cp = ftell(fp); |
| printf("cp = %li\n", cp); |
| |
| fputc(str[0], fp); |
| cp = ftell(fp); |
| printf("cp = %li\n", cp); |
| |
| rewind(fp); |
| cp = ftell(fp); |
| printf("cp = %li\n", cp); |
| fclose(fp); |
| return 0; |
| } |
| |
函数声明 |
int fseek ( FILE * stream, long offset, int where); |
所在文件 |
stdio.h |
函数功能 |
偏移文件指针。 |
参数及返回解析 |
|
参 数 |
FILE * stream 文件句柄 |
|
long offset 偏移量 |
|
int where 偏移起始位置 |
返回值 |
int 成功返回 0 ,失败返回 - 1 |
| #define SEEK_CUR 1 当前文字 |
| #define SEEK_END 2 文件结尾 |
| #define SEEK_SET 0 文件开头 |
| #include |
| |
| int main() |
| { |
| FILE *fp = fopen("test.txt", "w+"); |
| fputs("123456789", fp); |
| |
| fseek(fp, 0, SEEK_END); |
| int len = ftell(fp); |
| printf("len = %i\n", len); |
| fclose(fp); |
| return 0; |
| } |
| |
| #include |
| |
| int main() |
| { |
| FILE *fp; |
| fp = fopen("file.txt","w+"); |
| fputs("123456789", fp); |
| |
| fseek( fp, 7, SEEK_SET ); |
| fputs("lnj", fp); |
| fclose(fp); |
| return 0; |
| } |
| |
噢噢噢噢噢噢噢噢哦哦
哦