Skip to content

Commit

Permalink
doc: add file_io document.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywcjlove committed May 4, 2022
1 parent bd8fe53 commit b42aa86
Show file tree
Hide file tree
Showing 4 changed files with 367 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ C 和 C++ 的主要区别在于 C++ 支持类和对象,而 C 不支持
- [C 递归](docs/c_functions_recursion.md)
- [C 数学函数](docs/c_math.md)
- [C 结构](docs/c_structs.md)
- [C 中文件处理](docs/c_file_io.md)
- [C 关键字 Keywords](docs/c_keywords.md)

<!--idoc:ignore:end-->
Expand Down
361 changes: 361 additions & 0 deletions docs/c_file_io.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,361 @@
C 中文件处理
===

在编程中,我们可能需要多次生成某些特定的输入数据。有时,仅在控制台上显示数据是不够的。要显示的数据可能非常大,在控制台上只能显示有限的数据,而且由于内存是容易丢失的,不可能一次又一次地恢复程序生成的数据。 但是,如果我们需要这样做,我们可以将其存储到本地文件系统中,该文件系统是易失的,并且每次都可以访问。 在这里,需要在 C 中处理文件。

C 中的文件处理使我们能够通过我们的 C 程序创建、更新、读取和删除存储在本地文件系统中的文件。 可以对文件执行以下操作。

- 创建新文件
- 打开现有文件
- 从文件中读取
- 写入文件
- 删除文件

## 文件处理函数

C 库中有许多函数可以打开、读取、写入、搜索和关闭文件。 文件函数列表如下:

函数 | 描述 Description
---- | ----
fopen() | 打开新文件或现有文件
fprintf() | 将数据写入文件
fscanf() | 从文件中读取数据
fputc() | 将一个字符写入文件
fgetc() | 从文件中读取一个字符
fclose() | 关闭文件
fseek() | 将文件指针设置到给定位置
fputw() | 将整数写入文件
fgetw() | 从文件中读取一个整数
ftell() | 返回当前位置
rewind() | 将文件指针设置为文件的开头
<!--rehype:style=width: 100%; display: inline-table;-->

## 打开文件:fopen()

我们必须先打开一个文件,然后它才能被读取、写入或更新。`fopen()` 函数用于打开文件。`fopen()` 的语法如下所示:

```c
FILE *fopen( const char * filename, const char * mode );
```
fopen() 函数接受两个参数:
- 文件名(字符串)。 如果文件存储在某个特定位置,那么我们必须提及文件存储的路径。例如,文件名可以像“/some_folder/some_file.ext”。
- 打开文件的模式。 它是一个字符串。
我们可以在 fopen() 函数中使用以下模式之一。
模式 Mode | 描述 Description
---- | ----
r | 以读取模式打开一个文本文件,允许读取文件。
w | 以写模式打开一个文本文件,允许写入文件。
a | 以追加模式打开一个文本文件,如果文件不存在,则会创建一个新文件。
r+ | 以读写模式打开一个文本文件,允许读写文件。
w+ | 以读写模式打开一个文本文件,允许读写文件。
a+ | 以读写模式打开一个文本文件,允许读写文件。
rb | 以读取模式打开二进制文件
wb | 以写入模式打开二进制文件
ab | 以追加模式打开二进制文件
rb+ | 以读写模式打开二进制文件
wb+ | 以读写模式打开二进制文件
ab+ | 以读写模式打开二进制文件
<!--rehype:style=width: 100%; display: inline-table;-->
```c
#include<stdio.h>
void main( ) {
FILE *fp;
char ch;
fp = fopen("file_handle.c", "r");
while (1) {
ch = fgetc(fp);
if (ch == EOF)
break;
printf("%c", ch);
}
fclose(fp);
}
```

输出,将打印文件的内容:

```bash
#include<stdio.h>
void main( ) {
FILE *fp;
char ch;
fp = fopen("file_handle.c", "r");
while (1) {
ch = fgetc(fp);
if (ch == EOF)
break;
printf("%c", ch);
}
fclose(fp);
}
```
## 关闭文件:fclose()
`fclose()` 函数用于关闭文件。 对文件执行所有操作后,必须关闭该文件。`fclose()` 函数的语法如下:
```c
int fclose(FILE *fp);
```

## 写入文件:fprintf()

`fprintf()` 函数用于将字符集写入文件。 它将格式化的输出发送到流。
```c
int fprintf(FILE *stream, const char *format [, argument, ...])
```
```c
#include <stdio.h>
main() {
FILE *fp;
fp = fopen("file.txt", "w"); // 打开文件
fprintf(fp, "Hello file by fprintf...\n"); // 将数据写入文件
fclose(fp); // 关闭文件
}
```
## 读取文件:fscanf()
`fscanf()` 函数用于从文件中读取字符集。 它从文件中读取一个单词并在文件末尾返回 EOF。
```c
int fscanf(FILE *stream, const char *format [, argument, ...])
```
```c
#include <stdio.h>
main(){
FILE *fp;
char buff[255]; // 创建 char 数组来存储文件数据
fp = fopen("file.txt", "r");
while(fscanf(fp, "%s", buff)!=EOF) {
printf("%s ", buff);
}
fclose(fp);
}
```
## C 文件示例:存储员工信息
让我们看一个文件处理示例,用于存储用户从控制台输入的员工信息。 我们将存储员工的 ID、姓名和薪水。
```c
#include <stdio.h>
void main() {
FILE *fptr;
int id;
char name[30];
float salary;
fptr = fopen("emp.txt", "w+"); /* 打开文件 */
if (fptr == NULL) {
printf("文件不存在 \n");
return;
}
printf("Enter the id\n");
scanf("%d", &id);
fprintf(fptr, "Id= %d\n", id);
printf("Enter the name \n");
scanf("%s", name);
fprintf(fptr, "Name= %s\n", name);
printf("Enter the salary\n");
scanf("%f", &salary);
fprintf(fptr, "Salary= %.2f\n", salary);
fclose(fptr);
}
```
输出
```bash
Enter the id
1
Enter the name
kenny
Enter the salary
120000
```
现在从当前目录打开文件。你会看到 emp.txt 文件。它有以下信息:
```bash
Id= 1
Name= kenny
Salary= 120000
```
## 写入文件:fputc()
`fputc()` 函数用于将单个字符写入文件。它将一个字符输出到一个字符串
```c
int fputc(int c, FILE *stream)
```
```c
#include <stdio.h>
main(){
FILE *fp;
fp = fopen("file1.txt", "w"); // 打开文件
fputc('a',fp); // 将单个字符写入文件
fclose(fp); // 关闭文件
}
```
## 读取文件:fgetc()
`fgetc()` 函数从文件中返回单个字符。它从流中获取一个字符。它在文件末尾返回 EOF:
```c
int fgetc(FILE *stream)
```
```c
#include<stdio.h>
#include<conio.h>
void main() {
FILE *fp;
char c;
clrscr();
fp=fopen("myfile.txt", "r");
while((c=fgetc(fp))!=EOF){
printf("%c", c);
}
fclose(fp);
getch();
}
```
## 写入文件:fputs()
`fputs()` 函数将一行字符写入文件。它将字符串输出到流
```c
int fputs(const char *s, FILE *stream)
```
```c
#include<stdio.h>
#include<conio.h>
void main(){
FILE *fp;
clrscr();
fp = fopen("myfile2.txt","w");
fputs("hello c programming",fp);
fclose(fp);
getch();
}
```
## 读取文件:fgets()
`fgets()` 函数从文件中读取一行字符。 它从流中获取字符串:
```c
char* fgets(char *s, int n, FILE *stream)
```
```c
#include<stdio.h>
#include<conio.h>
void main() {
FILE *fp;
char text[300];
clrscr();

fp=fopen("myfile2.txt", "r");
printf("%s", fgets(text, 200, fp));
fclose(fp);
getch();
}
```
## fseek()
`fseek()` 函数用于将文件指针设置为指定的偏移量。 它用于将数据写入所需位置的文件:
```c
int fseek(FILE *stream, long int offset, int whence)
```
`fseek()` 函数中使用了 3 个常量:`SEEK_SET``SEEK_CUR``SEEK_END`
```c
#include <stdio.h>
void main(){
FILE *fp;
fp = fopen("myfile.txt","w+");
fputs("This is Book", fp);

fseek(fp, 7, SEEK_SET);
fputs("Kenny Wong", fp);
fclose(fp);
}
```
## rewind()
`rewind()` 函数将文件指针设置在流的开头。 如果您必须多次使用流,这很有用:
```c
void rewind(FILE *stream)
```
```c
#include<stdio.h>
#include<conio.h>
void main(){
FILE *fp;
char c;
clrscr();
fp=fopen("file.txt", "r");
while((c=fgetc(fp)) != EOF){
printf("%c", c);
}
rewind(fp); // 将文件指针移动到文件的开头
while((c=fgetc(fp)) != EOF){
printf("%c", c);
}
fclose(fp);
getch();
}
// 输出
// Hello World!Hello World!
```
如您所见,`rewind()` 函数将文件指针移动到文件的开头,这就是 `Hello World!` 被打印 2 次的原因。 如果你不调用 `rewind()` 函数,“Hello World!” 将只打印一次。
## ftell()
`ftell()` 函数返回指定流的当前文件位置。 我们可以使用 `ftell()` 函数在文件末尾移动文件指针后获取文件的总大小。 我们可以使用 `SEEK_END` 常量将文件指针移动到文件末尾。
```c
long int ftell(FILE *stream)
```

```c
#include <stdio.h>
#include <conio.h>
void main (){
FILE *fp;
int length;
clrscr();
fp = fopen("file.txt", "r");
fseek(fp, 0, SEEK_END);
length = ftell(fp);
fclose(fp);
printf("Size of file: %d bytes", length);
getch();
}
// 输出
// Size of file: 18 bytes
```
3 changes: 2 additions & 1 deletion docs/c_keywords.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ typedef | 用以给数据类型取别名 | goto | 无条件跳转语句
unsigned | 声明无符号类型变量或函数 | [break](./c_break_continue.md) | 跳出当前循环
signed | 声明有符号类型变量或函数 | default | 开关语句中的“其他”分支
extern | 声明变量是在其他文件正声明 | sizeof | 计算数据类型长度
register | 声明寄存器变量 | return | 子程序返回语句(可以带参数,也可不带参数)循环条件
register | 声明寄存器变量 | return | 子程序返回语句(可以带参数,也可不带参数)循环条件
<!--rehype:style=width: 100%; display: inline-table;-->
3 changes: 3 additions & 0 deletions idoc.chapters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
- /: 结构
- c_structs.md: C 结构 Structures

- /: 文件处理
- c_file_io.md: C 文件处理

- /: 参考
- c_keywords.md: C 关键字 Keywords

0 comments on commit b42aa86

Please sign in to comment.