# 在 C 编程中进行文件 I/O

> 原文： [https://beginnersbook.com/2014/01/c-file-io/](https://beginnersbook.com/2014/01/c-file-io/)

在本指南中，我们将学习如何使用 [C 编程](https://beginnersbook.com/2014/01/c-tutorial-for-beginners-with-examples/)语言对文件执行输入/输出（I/O）操作。

在我们详细讨论每个操作之前，让我们来看一个简单的 C 程序：

### 一个简单的 C 程序，用于打开，读取和关闭文件

```c
#include <stdio.h>
int main()
{
     /* Pointer to the file */
     FILE *fp1;
     /* Character variable to read the content of file */
     char c;

     /* Opening a file in r mode*/
     fp1= fopen ("C:\\myfiles\\newfile.txt", "r");

     /* Infinite loop –I have used break to come out of the loop*/
     while(1)
     {
        c = fgetc(fp1);
        if(c==EOF)
            break;
        else
            printf("%c", c);
     }
     fclose(fp1);
     return 0;
}
```

在上面的程序中，我们在`r`模式下打开文件`newfile.txt`，读取文件内容并在控制台上显示。让我们详细了解每个操作：

## 1\. 打开文件

`fopen()`函数用于打开文件。

**语法：**

```c
FILE pointer_name = fopen ("file_name", "Mode");
```

`pointer_name`可以是您选择的任何东西。

`file_name`是您要打开的文件的名称。在此处指定完整路径，如`C:\\myfiles\\newfile.txt`。

打开文件时，需要指定模式。我们用来读取文件的模式是`r`，它是“只读模式”。

**例如：**

```c
FILE  *fp;
fp = fopen("C:\\myfiles\\newfile.txt", "r");
```

第一个字符的地址存储在`pointer fp`中。

**如何检查文件是否已成功打开？**

如果文件未成功打开，则指针将被赋予`NULL`值，因此您可以编写如下逻辑：

此代码将检查文件是否已成功打开。如果文件未打开，则会向用户显示错误消息。

```c
..
FILE fpr;
fpr = fopen("C:\\myfiles\\newfile.txt", "r");
if (fpr == NULL)
{
    puts("Error while opening file");
    exit();
}
```

### 各种文件打开模式：

使用`fopen()`函数打开文件，打开时可以根据需要使用以下任何一种模式。

**模式`r`**：这是一种只读模式，这意味着如果文件在`r`模式下打开，它将不允许您编写和修改它的内容。当`fopen()`成功打开文件时，它返回文件第一个字符的地址，否则返回`NULL`。

**模式`w`**：这是一种只写模式。`fopen()`函数在指定文件不存在时创建新文件，如果无法打开文件，则返回`NULL`。

**模式`a`**：使用此模式，内容可以附加在现有文件的末尾。与模式`w`类似，如果文件不存在，`fopen()`会创建一个新文件。在打开不成功时，它返回`NULL`。文件指针指向：文件的最后一个字符。

**模式`r+`**：此模式与模式`r`相同；但是，您可以对在此模式下打开的文件执行各种操作。您可以读取，写入和修改以`r+`模式打开的文件内容。文件指针指向：文件的第一个字符。

**模式`w+`**：与可以执行的操作相同的模式`w`相同；可以在此模式下读取，写入和修改文件。

**模式`a+`**：与模式`a`相同;您可以在文件中读取和附加数据，但在此模式下不允许进行内容修改。

## 2\. 读取文件

要读取文件，我们必须首先使用任何模式打开它，例如，如果您只想读取文件，然后以`r`模式打开它。根据文件打开期间选择的模式，我们可以对文件执行某些操作。

### C 程序：读取文件

**`fgetc()`：**该函数从当前指针的位置读取字符，成功读取后，将指针移动到文件中的下一个字符。一旦指针到达文件的末尾，该函数返回 **EOF（文件结束）**。我们在程序中使用了 **EOF** 来确定文件的结尾。

```c
#include <stdio.h>
int main()
{
     /* Pointer to the file */
     FILE *fp1;
     /* Character variable to read the content of file */
     char c;

     /* Opening a file in r mode*/
     fp1= fopen ("C:\\myfiles\\newfile.txt", "r");

     /* Infinite loop –I have used break to come out of the loop*/
     while(1)
     {
        c = fgetc(fp1);
        if(c==EOF)
            break;
        else
            printf("%c", c);
     }
     fclose(fp1);
     return 0;
}
```

## 3.写入文件

要写入文件，我们必须以支持写入的模式打开文件。例如，如果以`r`模式打开文件，则无法写入文件，因为`r`是只允许读取的只读模式。

## 示例：C 程序写入文件

该程序要求用户输入一个字符并将该字符写在文件的末尾。如果该文件不存在，则该程序将创建具有指定名称的文件，并将输入字符写入文件。

```c
#include <stdio.h>
int main()
{
   char ch;
   FILE *fpw;
   fpw = fopen("C:\\newfile.txt","w");

   if(fpw == NULL)
   {
      printf("Error");   
      exit(1);             
   }

   printf("Enter any character: ");
   scanf("%c",&ch);

   /* You can also use fputc(ch, fpw);*/
   fprintf(fpw,"%c",ch);
   fclose(fpw);

   return 0;
}
```

## 4\. 关闭文件

```c
fclose(fp);
```

**`fclose()`**函数用于关闭打开的文件。作为参数，您必须提供指向要关闭的文件的指针。

### 在 C 中显示打开，读取，写入和关闭操作的示例

```c
#include <stdio.h>
int main()
{
    char ch;

    /* Pointer for both the file*/
    FILE *fpr, *fpw;
    /* Opening file FILE1.C in “r” mode for reading */
    fpr = fopen("C:\\file1.txt", "r");

    /* Ensure FILE1.C opened successfully*/
    if (fpr == NULL)
    {
         puts("Input file cannot be opened");
    }

    /* Opening file FILE2.C in “w” mode for writing*/
    fpw= fopen("C:\\file2.txt", "w");

    /* Ensure FILE2.C opened successfully*/
    if (fpw == NULL)
    {
       puts("Output file cannot be opened");
    }

    /*Read & Write Logic*/
    while(1)
    {
        ch = fgetc(fpr);
        if (ch==EOF)
            break;
        else
            fputc(ch, fpw);
    }

    /* Closing both the files */
    fclose(fpr);
    fclose(fpw);

    return 0;
}
```

## 如何在文件中读/写（I/O）字符串 - `fgets`和`fputs`

在这里，我们将讨论如何读字符串和将其写到文件中。

```c
char *fgets(char *s, int rec_len, FILE *fpr)
```

**`s`** ：存储字符串的字符数组。

**`rec_len`** ：输入记录的长度。

**`fpr`** ：指向输入文件的指针。

让我们举一个例子：

### 在 C 编程中从文件中读取字符串的示例

```c
#include <stdio.h>
int main()
{
    FILE *fpr;
    /*Char array to store string */
    char str[100];
    /*Opening the file in "r" mode*/
    fpr = fopen("C:\\mynewtextfile.txt", "r");

    /*Error handling for file open*/
    if (fpr == NULL)
    {
       puts("Issue in opening the input file");
    }

    /*Loop for reading the file till end*/
    while(1)
    {
       if(fgets(str, 10, fpr) ==NULL)
            break;
       else
            printf("%s", str);
    }
    /*Closing the input file after reading*/
    fclose(fpr);
    return 0;
}
```

在上面的例子中，我们使用了这样的`fgets`函数：

```c
fgets(str, 10, fpr)
```

这里 **`str`**表示从文件中读取字符串后，存储字符串的缓冲区（`char`数组）。**`10`** 是每次需要读取的字符串的长度。**`fpr`** 是指向文件的指针，将被读取。

**为什么我用`if(fgets(str, 10, fpr) ==NULL)`作为判断文件结尾的逻辑？**

在上面的例子中，我们用`ch == EOF`来知道文件的结尾。这里我们使用了这个逻辑，因为当没有更多的记录可供读取时，`fgets`返回`NULL`。

### C 程序 - 将字符串写入文件

```c
int fputs ( const char * s, FILE * fpw );
```

`char *s` - `char`数组。

`FILE *fpw` - 指向文件的指针（`FILE`类型），将被写入。

```c
#include <stdio.h>
int main()
{
     FILE *fpw;

     /*Char array to store strings */
     char str[100];

     /*Opening the file FILEW.TXT in "w" mode for writing*/
     fpw = fopen("C:\\mynewtextfile2.txt", "w");

     /*Error handling for output file*/
     if (fpw== NULL)
     {
          puts("Issue in opening the Output file");
     }

     printf("Enter your string:");

     /*Stored the input string into array – str*/
     gets(str);

     /* Copied the content of str into file – 
      * mynewtextfile2.txt using pointer – fpw
      */
     fputs(str, fpw);

     /*Closing the Output file after successful writing*/
     fclose(fpw);
     return 0;
}
```

**`fputs`有两个参数：**

```c
fputs(str, fpw)
```

**`str`** - `str`表示存储字符串的数组。

**`fpw`** - 指向输出文件的`FILE`指针，需要在其中写入记录。

**关于`fputs`的注意事项：默认情况下**

`fputs`在写入每条记录后不会添加新行，为了手动执行此操作 - 每次写入文件后都可以使用以下语句。

```c
fputs("\n", fpw);
```

## C 文件 I/O：二进制文件

到目前为止，我们已经学习了文本文件的文件操作，如果文件是二进制文件（例如`.exe`文件）。上述程序不适用于二进制文件，但处理二进制文件时有一些细微的变化。主要区别在于**文件名和模式。** 让我们在一个例子的帮助下理解这一点。可以说我有两个二进制文件`bin1.exe`和`bin2.exe`- 我想将`bin1.exe`的内容复制到`bin2.exe`：

### 示例：在 C 中读取和写入二进制文件

```c
#include <stdio.h>
int main()
{
    char ch;

    /* Pointers for both binary files*/
    FILE *fpbr, *fpbw;

    /* Open for bin1.exe file in rb mode */
    fpbr = fopen("bin1.exe", "rb");

    /* test logic for successful open*/
    if (fpbr == NULL)
    {
        puts("Input Binary file is having issues while opening");
    }

    /* Opening file bin2.exe in “wb” mode for writing*/
    fpbw= fopen("bin2.exe", "wb");

    /* Ensure bin2.exe opened successfully*/
    if (fpbw == NULL)
    {
       puts("Output binary file is having issues while opening");
    }

    /*Read & Write Logic for binary files*/
    while(1)
    {
        ch = fgetc(fpbr);
        if (ch==EOF)
             break;
         else
             fputc(ch, fpbw);
     }

     /* Closing both the binary files */
     fclose(fpbr);
     fclose(fpbw);

     return 0;
}
```

**注意：文件打开模式为`rb`和`wb`而不是`r`和`w`**

