今有文件 **test.txt** 文件内容如下: aBcDEfoKr# ,以 # 为结束,实现一个函数将其大小写转换输出到控制台和修改保存源文件。
b12@PC:~/chapter13$ mkdir datab12@PC:~/chapter13$ echo 'aBcDEfoKr#' > ./data/test.txtb12@PC:~/chapter13$ cat ./data/test.txtaBcDEfoKr#
34、在打开文件时,指定的文件名找不到
错误示范:文件名不对或该路径下没有该文件造成错误!
#include <stdio.h>#include <stdlib.h>int main () {FILE *fp = fopen("./data/test", "r");if (NULL == fp) {printf("Error: can not open file\n");exit(0);}printf("Reading file successfully\n");// fclose(fp);return 0;}
编译运行:
:::success
b12@PC:~/chapter13$ gcc ./src/IO.c -o ./bin/IO
b12@PC:~/chapter13$ ./bin/IO
Error: can not open file
:::
拓展延申:在 Linux 下,有头文件 unistd.h 专门访问 Unix 平台的一系列函数,在 Windows 下不行!这里演示下获取工作目录。具体用法见官网, getcwd,getwd 两者都要申请内存用作函数填充路径问题。但是用 get_current_dir_name 比较方便。
NAMEgetcwd, getwd, get_current_dir_name - get current working directorySYNOPSIS#include <unistd.h>char *getcwd(char *buf, size_t size);char *getwd(char *buf);char *get_current_dir_name(void);
当然我们也可以鸡贼调用 shell 命令 ls 帮我们打印当前目录信息。
#include <stdio.h>#include <stdlib.h>int main () {FILE *fp = fopen("./data/test.txt", "r"); // 注意路径if (NULL == fp) {printf("Error: can not open file\n");exit(0);}char ch = fgetc(fp);while ('#' != ch) {if ('A' <= ch && ch <= 'Z') {putchar(ch + 32);} else {putchar(ch - 32);}ch = fgetc(fp);}printf("\n");system("ls");fclose(fp);return 0;}
编译运行:
:::success
(base) b12@PC:~/chapter13$ gcc ./src/IO.c -o ./bin/IO
b12@PC:~/chapter13$ ./bin/IO
AbCdeFOkR
bin data src
(base) b12@PC:~/chapter13$ cat ./data/test.txt
aBcDEfoKr#
:::
但是上面的程序只是在控制台输出,然而源文件没有被修改过!修改见下面代码
33、使用文件时忘记打开,或打开方式与使用情况不匹配
错误示范: r 打开又读又写。
#include <stdio.h>#include <stdlib.h>int main () {FILE *fp = fopen("./data/test.txt", "r");if (NULL == fp) {printf("Error: can not open file\n");exit(0);}char ch = fgetc(fp);while ('#' != ch) {if ('A' <= ch && ch <= 'Z') {putchar(ch + 32);fputc(ch + 32, fp);} else {putchar(ch - 32);fputc(ch - 32, fp);}ch = fgetc(fp);}printf("\n");fclose(fp);return 0;}
编译运行:
:::success
(base) b12@PC:~/chapter13$ gcc ./src/IO.c -o ./bin/IO
(base) b12@PC:~/chapter13$ ./bin/IO
AbCdeFOkR
(base) b12@PC:~/chapter13$ cat ./data/test.txt
aBcDEfoKr#
:::
可见没有报错,但是最终文件却没有被写入保存。
正确做法:重新创建临时文件 tmp.txt ,然后写入后,删除 test.txt 文件重命名临时文件 tmp.txt 为test.txt 。
#include <stdio.h>#include <stdlib.h>char *originFile = "./data/test.txt";char *tmpFile = "./data/tmp.txt";int main () {FILE *fp1 = fopen(originFile, "r");if (NULL == fp1) {printf("Error: can not open %s file\n", originFile);exit(0);}FILE *fp2 = fopen(tmpFile, "w");if (NULL == fp2) {printf("Error: can not build %s file\n", tmpFile);exit(0);}char ch = fgetc(fp1);while ('#' != ch) {if ('A' <= ch && ch <= 'Z') {putchar(ch + 32);fputc(ch + 32, fp2);} else {putchar(ch - 32);fputc(ch - 32, fp2);}ch = fgetc(fp1);}printf("\n");fclose(fp1);// 1.删除原文件名if (0 != remove(originFile)) {printf("Error:can not remove %s!\n", originFile);exit(0);}// 2.将 tmp 文件重命名为 test.txt (偷天换日)if (0 != rename(tmpFile, originFile)) {printf("Error:can not rename %s!\n", tmpFile);exit(0);}fclose(fp2);return 0;}
编译运行:
:::success
(base) b12@PC:~/chapter13$ gcc ./src/IO.c -o ./bin/IO
(base) b12@PC:~/chapter13$ ./bin/IO
AbCdeFOkR
(base) b12@PC:~/chapter13$ cat ./data/test.txt
AbCdeFOkR
:::
35、忘记关闭文件,虽然系统会自动关闭所用文件,但可能会丢失数据。因此必须在用完文件后关闭它
操作系统在进行 IO 时,有一个缓冲区,一般都是行缓冲(即为何你输入数据后要按下回车)可以设置超过多少后就进行处理。那么如果在缓冲区内含有数据尚未输出到磁盘之前就会关闭文件,那么就会造成数据丢失。
