今有文件 **test.txt**
文件内容如下: aBcDEfoKr#
,以 #
为结束,实现一个函数将其大小写转换输出到控制台和修改保存源文件。
b12@PC:~/chapter13$ mkdir data
b12@PC:~/chapter13$ echo 'aBcDEfoKr#' > ./data/test.txt
b12@PC:~/chapter13$ cat ./data/test.txt
aBcDEfoKr#
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
比较方便。
NAME
getcwd, getwd, get_current_dir_name - get current working directory
SYNOPSIS
#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
时,有一个缓冲区,一般都是行缓冲(即为何你输入数据后要按下回车)可以设置超过多少后就进行处理。那么如果在缓冲区内含有数据尚未输出到磁盘之前就会关闭文件,那么就会造成数据丢失。