C语言程序设计(下):文件操作技术指南
发布时间: 2024-01-27 01:55:55 阅读量: 37 订阅数: 41
# 1. 引言
## 1.1 文件操作的重要性
文件操作是计算机编程中非常重要的一部分,它涉及到读取和写入文件的内容,并且能够实现数据的永久保存和共享。无论是存储用户数据、备份重要文件、处理大量数据等等,文件操作都是必不可少的。
## 1.2 C语言中的文件概念
在C语言中,文件是指存储在外部存储介质上(如硬盘、U盘)的一组有序的数据。操作文件需要先打开文件,然后进行读写操作,最后关闭文件。C语言提供了丰富的函数和方法来操作文件。
## 1.3 本章内容概述
本章将介绍C语言中文件的打开和关闭操作,文件读取和写入的基本方法,文件指针的定位和偏移,以及文件管理和目录操作等内容。通过学习本章的知识,您将能够灵活运用C语言来进行文件操作,提高程序的实用性和灵活性。
接下来,请您阅读第二章:文件的打开和关闭。
# 2. 文件的打开和关闭
在本章中,我们将探讨如何在C语言中打开和关闭文件。文件操作是C语言中非常重要的一部分,通过文件操作,可以读取和写入数据,实现持久化存储,并且能够与外部环境进行数据交互。
### 2.1 打开文件的基本方法
在C语言中,可以使用`fopen()`函数来打开一个文件。它的基本语法如下:
```c
FILE *fopen(const char *filename, const char *mode);
```
其中,`filename`为要打开的文件名字符串,`mode`为打开文件的模式字符串。成功打开后,`fopen()`函数返回一个指向`FILE`类型的指针,该指针将作为后续文件操作的参数。
### 2.2 文件打开模式及其含义
在C语言中,文件打开模式由一些字符表示,常用的模式包括:
- "r":只读模式,打开一个文本文件,文件必须存在。
- "w":只写模式,创建一个空文件进行写操作,如果文件存在,则清空文件内容。
- "a":追加模式,打开一个文本文件进行写操作,如果文件存在,则在末尾追加数据。
- "r+":读写模式,打开一个文本文件进行读写操作,文件必须存在。
- "w+":读写模式,创建一个空文件进行读写操作,如果文件存在,则清空文件内容。
- "a+":读写模式,打开一个文本文件进行读写操作,如果文件存在,则在末尾追加数据。
### 2.3 错误处理与异常情况
在打开文件时,可能会遇到诸如文件不存在、无法访问等异常情况。为了处理这些情况,可以使用`fopen()`函数的返回值进行错误检查。
```c
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {
// 错误处理代码
fprintf(stderr, "无法打开文件!");
exit(EXIT_FAILURE);
}
```
### 2.4 文件的关闭操作
打开文件后,应该在不再需要访问文件时进行关闭,以释放系统资源。使用`fclose()`函数可以关闭文件。
```c
FILE *fp = fopen("example.txt", "r");
// 文件操作代码
fclose(fp);
```
### 2.5 实例演示:文件的打开和关闭
下面是一个简单的C语言程序,演示了如何打开和关闭文件:
```c
#include <stdio.h>
int main() {
FILE *fp;
fp = fopen("example.txt", "w");
if (fp == NULL) {
fprintf(stderr, "无法打开文件!");
return 1;
}
fprintf(fp, "这是一个示例文件!");
fclose(fp);
return 0;
}
```
在这个示例中,我们首先使用`fopen()`函数打开一个文件,然后进行写操作,最后使用`fclose()`函数关闭文件。这样就完成了文件的打开和关闭操作。
通过本章的学习,我们了解了在C语言中如何打开和关闭文件,以及相关的错误处理方法。在下一章节中,我们将学习如何进行文件的读取和写入操作。
# 3. 读取和写入文件
### 3.1 基本的读写文件函数:fgetc、fputc
在C语言中,我们可以使用一些基本的函数来实现文件的读取和写入操作。其中,使用fgetc函数可以逐个字符地读取一个文件的内容,而使用fputc函数可以将一个字符写入到文件中。
```c
#include<stdio.h>
int main() {
FILE *file;
char c;
// 打开文件
file = fopen("example.txt", "r");
if (file == NULL) {
printf("文件打开失败!");
return 0;
}
// 逐个字符读取文件内容
while ((c = fgetc(file)) != EOF) {
printf("%c", c);
}
// 关闭文件
fclose(file);
return 0;
}
```
**代码说明:**
- 首先,我们使用fopen函数打开一个文本文件,其中第一个参数是文件名,第二个参数是打开文件的模式(这里使用了"r",表示只读模式)。
- 然后,我们通过一个while循环,使用fgetc函数逐个字符地读取文件的内容,直到文件结束标志EOF。
- 最后,使用fclose函数关闭文件。
### 3.2 逐行读取文件:fgets、fputs
除了逐个字符地读取文件,我们也可以逐行地读取文件的内容。为此,可以使用fgets函数逐行读取文件的内容,再使用fputs函数将字符串写入文件中。
```c
#include<stdio.h>
int main() {
FILE *file;
char line[100];
// 打开文件
file = fopen("example.txt", "r");
if (file == NULL) {
printf("文件打开失败!");
return 0;
}
// 逐行读取文件内容
while (fgets(line, sizeof(line), file) != NULL) {
printf("%s", line);
}
// 关闭文件
fclose(file);
return 0;
}
```
**代码说明:**
- 首先,我们使用fopen函数打开一个文本文件,具体操作和之前的示例一样。
- 然后,我们通过一个while循环,使用fgets函数逐行读取文件的内容,其中第一个参数是存放读取内容的字符数组,第二个参数是每行最大允许的字符数,第三个参数是文件指针。
- 最后,使用fclose函数关闭文件。
### 3.3 读写二进制文件:fread、fwrite
除了文本文件,C语言还可以读写二进制文件。可以使用fread函数从二进制文件中读取数据,使用fwrite函数将数据写入到二进制文件中。
```c
#include<stdio.h>
struct employee {
char name[50];
int age;
float salary;
};
int main() {
FILE *file;
struct employee emp;
// 打开文件
file = fopen("employee.dat", "rb");
if (file == NULL) {
printf("文件打开失败!");
return 0;
}
// 读取二进制文件内容
while (fread(&emp, sizeof(emp), 1, file) == 1) {
printf("Name: %s\n", emp.name);
printf("Age: %d\n", emp.age);
printf("Salary: %.2f\n\n", emp.salary);
}
// 关闭文件
fclose(file);
return 0;
}
```
**代码说明:**
- 首先,我们定义了一个结构体employee,其中包含了员工的姓名、年龄和薪水。
- 然后,我们使用fopen函数打开一个二进制文件,具体操作和之前的示例一样。注意,这里的文件打开模式是"rb",表示以二进制只读模式打开文件。
- 接着,使用fread函数逐个结构体地从二进制文件中读取数据,其中第一个参数是存放读取数据的结构体指针,第二个参数是结构体的大小,第三个参数是读取的数据个数,第四个参数是文件指针。
- 最后,使用fclose函数关闭文件。
### 3.4 实例演示:读取和写入文件
```c
#include<stdio.h>
int main() {
FILE *inFile;
FILE *outFile;
char c;
// 打开输入文件
inFile = fopen("input.txt", "r");
if (inFile == NULL) {
printf("输入文件打开失败!");
return 0;
}
// 打开输出文件
outFile = fopen("output.txt", "w");
if (outFile == NULL) {
printf("输出文件打开失败!");
return 0;
}
// 逐个字符地读取输入文件并将其写入输出文件
while ((c = fgetc(inFile)) != EOF) {
fputc(c, outFile);
}
// 关闭输入文件和输出文件
fclose(inFile);
fclose(outFile);
return 0;
}
```
**代码说明:**
- 首先,我们使用fopen函数打开一个输入文件,并将其指定为只读模式。
- 然后,我们使用fopen函数打开一个输出文件,并将其指定为只写模式。
- 接着,我们通过一个while循环,使用fgetc函数逐个字符地读取输入文件的内容,并使用fputc函数将该字符写入到输出文件中。
- 最后,我们使用fclose函数关闭输入文件和输出文件。
本章我们介绍了文件的读取和写入操作,包括基本的读写文件函数如fgetc、fputc,逐行读取文件的函数如fgets、fputs,以及读写二进制文件的函数如fread、fwrite。同时,我们通过一个实例演示了如何同时读取一个文件的内容并将其写入到另一个文件中。接下来,我们将继续介绍文件指针的定位。
# 4. 文件指针的定位
在文件操作中,文件指针是一个非常重要的概念,它指示了当前读写位置在文件中的偏移量。通过文件指针,我们可以对文件进行随机读写操作,而不仅仅局限于顺序读写。
#### 4.1 文件指针的概念
文件指针就是一个指针变量,在C语言中通常使用`FILE *`类型来声明一个文件指针。文件指针主要用于指示当前读写操作所在的位置,它会随着每次读写的操作而自动更新。
#### 4.2 定位文件指针的函数:fseek、ftell
在C语言中,我们可以使用`fseek`函数来设置文件指针的位置。其函数原型如下:
```c
int fseek(FILE *stream, long offset, int whence);
```
* `stream`:要操作的文件指针
* `offset`:偏移量,指定了从`whence`位置起的偏移量,可以是正数、负数或者0
* `whence`:定位方式,可以取以下值:
* `SEEK_SET`:从文件起始位置开始计算偏移
* `SEEK_CUR`:从当前文件指针位置开始计算偏移
* `SEEK_END`:从文件末尾位置开始计算偏移
除了`fseek`函数外,还有一个相关的函数`ftell`,用于获取当前文件指针的位置。其函数原型如下:
```c
long ftell(FILE *stream);
```
#### 4.3 文件指针的偏移量
文件指针的偏移量是一个长整型(`long`)的值,代表了当前读写位置相对于文件起始位置的距离。偏移量可以是正数、负数或者0,用来表示向后或向前移动的字节数。
#### 4.4 实例演示:文件指针的定位
下面是一个使用`fseek`和`ftell`函数的实例演示,来展示文件指针的定位操作:
```c
#include <stdio.h>
int main() {
FILE *file = fopen("data.txt", "r");
if (file == NULL) {
printf("文件打开失败!\n");
return 1;
}
// 定位文件指针到文件末尾
fseek(file, 0, SEEK_END);
// 获取当前文件指针的位置
long position = ftell(file);
printf("文件大小为:%ld 字节\n", position);
fclose(file);
return 0;
}
```
运行结果:
```
文件大小为:245 字节
```
在这个示例中,我们首先打开了一个名为`data.txt`的文件,并将文件指针定位到文件末尾。然后,使用`ftell`函数获取了当前文件指针的位置,即文件大小。最后,关闭文件。通过这个简单的例子,我们可以看到文件指针的定位操作是如何实现的,以及如何获取当前文件指针的位置。
在实际的文件操作中,文件指针的定位非常有用,它可以实现文件的随机读写,提高程序的灵活性和效率。根据具体的需求,我们可以根据偏移量和定位方式来操作文件指针,从而实现更加灵活的文件处理。
# 5. 文件管理和目录操作
在本章中,我们将学习C语言中文件和目录的管理操作。文件和目录的创建、删除、重命名、移动、复制、粘贴以及属性的查询和修改都是文件管理和目录操作的重要内容。
### 5.1 文件和目录的创建与删除
文件和目录的创建和删除是文件系统中最基本的操作之一。C语言提供了相应的函数来完成这些操作。
- **文件创建**
- 函数原型:int _mkdir(const char* path)
- 函数功能:创建一个新的文件
- 参数说明:
- path:要创建的文件路径名
- 返回值:操作成功返回0,失败返回-1
示例代码如下:
```c
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
int main() {
int result = mkdir("./example", 0755);
if (result == 0) {
printf("文件创建成功\n");
} else {
printf("文件创建失败\n");
}
return 0;
}
```
注释:
- mkdir函数用于创建一个新的目录,参数path指定要创建的目录路径名。
- mkdir函数的返回值为0表示创建成功,返回值为-1表示创建失败。
- 0755是权限掩码,授权所有者可读、可写、可执行,授权组可读,其他用户可读。
代码总结:
- 文件创建通过调用mkdir函数来实现。
- 创建成功时,返回值为0;创建失败时,返回值为-1。
结果说明:
- 当成功运行示例代码后,会在当前目录下创建一个名为example的目录。
- **文件删除**
- 函数原型:int _rmdir(const char* path)
- 函数功能:删除指定的文件
- 参数说明:
- path:要删除的文件路径名
- 返回值:操作成功返回0,失败返回-1
示例代码如下:
```c
#include <stdio.h>
#include <unistd.h>
int main() {
int result = rmdir("./example");
if (result == 0) {
printf("文件删除成功\n");
} else {
printf("文件删除失败\n");
}
return 0;
}
```
注释:
- rmdir函数用于删除指定的目录,参数path指定要删除的目录路径名。
- rmdir函数的返回值为0表示删除成功,返回值为-1表示删除失败。
代码总结:
- 文件删除通过调用rmdir函数来实现。
- 删除成功时,返回值为0;删除失败时,返回值为-1。
结果说明:
- 当成功运行示例代码后,会删除当前目录下名为example的目录。如果目录不存在或不为空,则删除操作将失败。
### 5.2 文件和目录的重命名与移动
文件和目录的重命名与移动操作是文件系统中常见的操作。C语言提供了相应的函数来完成这些操作。
- **文件重命名**
- 函数原型:int _rename(const char* oldpath, const char* newpath)
- 函数功能:将文件重命名为新的文件名
- 参数说明:
- oldpath:原文件路径名
- newpath:新文件路径名
- 返回值:操作成功返回0,失败返回-1
示例代码如下:
```c
#include <stdio.h>
int main() {
int result = rename("./example.txt", "./new_example.txt");
if (result == 0) {
printf("文件重命名成功\n");
} else {
printf("文件重命名失败\n");
}
return 0;
}
```
注释:
- rename函数用于将指定的文件重命名为新的文件名,参数oldpath指定原文件路径名,参数newpath指定新文件路径名。
- rename函数的返回值为0表示重命名成功,返回值为-1表示重命名失败。
代码总结:
- 文件重命名通过调用rename函数来实现。
- 重命名成功时,返回值为0;重命名失败时,返回值为-1。
结果说明:
- 当成功运行示例代码后,会将当前目录下名为example.txt的文件重命名为new_example.txt。
- **文件移动**
- 函数原型:int _rename(const char* oldpath, const char* newpath)
- 函数功能:将文件移动到新的路径
- 参数说明:
- oldpath:原文件路径名
- newpath:新文件路径名
- 返回值:操作成功返回0,失败返回-1
示例代码如下:
```c
#include <stdio.h>
int main() {
int result = rename("./example.txt", "./example_dir/example.txt");
if (result == 0) {
printf("文件移动成功\n");
} else {
printf("文件移动失败\n");
}
return 0;
}
```
注释:
- rename函数还可以用于将指定的文件移动到新的路径,参数oldpath指定原文件路径名,参数newpath指定新文件路径名。
- rename函数的返回值为0表示移动成功,返回值为-1表示移动失败。
代码总结:
- 文件移动通过调用rename函数来实现。
- 移动成功时,返回值为0;移动失败时,返回值为-1。
结果说明:
- 当成功运行示例代码后,会将当前目录下名为example.txt的文件移动到example_dir目录下。
### 5.3 文件和目录的复制与粘贴
文件和目录的复制和粘贴是文件管理中常见的操作之一。C语言可以通过一些函数实现文件和目录的复制与粘贴。
- **文件复制**
- 函数原型:int _copy(const char* source, const char* dest)
- 函数功能:将文件从源路径复制到目标路径
- 参数说明:
- source:源文件路径
- dest:目标文件路径
- 返回值:操作成功返回0,失败返回-1
示例代码如下:
```c
#include <stdio.h>
int main() {
int result = copy("./example.txt", "./copy_example.txt");
if (result == 0) {
printf("文件复制成功\n");
} else {
printf("文件复制失败\n");
}
return 0;
}
```
注释:
- 自定义的copy函数可实现将文件从源路径复制到目标路径的功能。
- copy函数的返回值为0表示复制成功,返回值为-1表示复制失败。
代码总结:
- 文件复制通过调用自定义的copy函数来实现。
- 复制成功时,返回值为0;复制失败时,返回值为-1。
结果说明:
- 当成功运行示例代码后,会将当前目录下名为example.txt的文件复制到当前目录下并命名为copy_example.txt。
- **目录复制**
- 函数原型:int _copy_dir(const char* source, const char* dest)
- 函数功能:将目录及其下的文件从源路径复制到目标路径
- 参数说明:
- source:源目录路径
- dest:目标目录路径
- 返回值:操作成功返回0,失败返回-1
示例代码如下:
```c
#include <stdio.h>
int main() {
int result = copy_dir("./example_dir", "./copy_example_dir");
if (result == 0) {
printf("目录复制成功\n");
} else {
printf("目录复制失败\n");
}
return 0;
}
```
注释:
- 自定义的copy_dir函数可实现将目录及其下的文件从源路径复制到目标路径的功能。
- copy_dir函数的返回值为0表示复制成功,返回值为-1表示复制失败。
代码总结:
- 目录复制通过调用自定义的copy_dir函数来实现。
- 复制成功时,返回值为0;复制失败时,返回值为-1。
结果说明:
- 当成功运行示例代码后,会将当前目录下名为example_dir的目录及其下的文件复制到当前目录下并命名为copy_example_dir。
### 5.4 文件和目录的属性查询和修改
文件和目录的属性查询和修改是文件管理和目录操作中常见的操作之一。C语言提供了一些函数来查询和修改文件和目录的属性。
- **文件属性查询**
- 函数原型:int _stat(const char* path, struct stat* buf)
- 函数功能:获取指定文件的属性信息
- 参数说明:
- path:要查询的文件路径名
- buf:用于存储文件属性信息的结构体
- 返回值:操作成功返回0,失败返回-1
示例代码如下:
```c
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
int main() {
struct stat info;
int result = stat("./example.txt", &info);
if (result == 0) {
printf("文件大小:%ld bytes\n", info.st_size);
printf("文件权限:%o\n", info.st_mode & 07777);
printf("最后访问时间:%ld\n", info.st_atime);
} else {
printf("文件属性查询失败\n");
}
return 0;
}
```
注释:
- stat函数用于获取指定文件的属性信息,参数path指定要查询的文件路径名,参数buf是一个用于存储文件属性信息的结构体(stat结构体)。
- stat函数的返回值为0表示查询成功,返回值为-1表示查询失败。
- **文件属性修改**
- 函数原型:int _chmod(const char* path, mode_t mode)
- 函数功能:修改文件的权限
- 参数说明:
- path:要修改的文件路径名
- mode:要修改的文件权限
- 返回值:操作成功返回0,失败返回-1
示例代码如下:
```c
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
int main() {
int result = chmod("./example.txt", 0644);
if (result == 0) {
printf("文件权限修改成功\n");
} else {
printf("文件权限修改失败\n");
}
return 0;
}
```
注释:
- chmod函数用于修改指定文件的权限,参数path指定要修改的文件路径名,参数mode指定要修改的文件权限。
- chmod函数的返回值为0表示修改成功,返回值为-1表示修改失败。
代码总结:
- 文件属性查询通过调用stat函数来实现。
- 文件属性修改通过调用chmod函数来实现。
- 查询或修改成功时,返回值为0;查询或修改失败时,返回值为-1。
结果说明:
- 当成功运行示例代码后,会查询并显示当前目录下名为example.txt文件的大小、权限以及最后访问时间。
- 修改权限成功后,可以通过ls -l命令来查看文件权限是否已修改。
### 实例演示:文件管理和目录操作
接下来,我们将通过一个实例演示文件管理和目录操作的具体使用方法。
```c
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
int main() {
// 创建目录
int create_result = mkdir("./example_dir", 0755);
if (create_result == 0) {
printf("目录创建成功\n");
} else {
printf("目录创建失败\n");
exit(1);
}
// 创建文件
FILE *file = fopen("./example_dir/example.txt", "w");
if (file != NULL) {
fputs("Hello, File!", file);
fclose(file);
printf("文件创建成功\n");
} else {
printf("文件创建失败\n");
}
// 修改文件权限
int chmod_result = chmod("./example_dir/example.txt", 0644);
if (chmod_result == 0) {
printf("文件权限修改成功\n");
} else {
printf("文件权限修改失败\n");
}
// 删除文件和目录
int remove_file_result = remove("./example_dir/example.txt");
int remove_dir_result = rmdir("./example_dir");
if (remove_file_result == 0 && remove_dir_result == 0) {
printf("文件和目录删除成功\n");
} else {
printf("文件和目录删除失败\n");
}
return 0;
}
```
注释:
- 该示例代码依次执行了创建目录、创建文件、修改文件权限和删除文件和目录的操作。
- 运行示例代码后,会在当前目录下创建一个名为example_dir的目录,然后在该目录下创建一个名为example.txt的文件,并将字符串"Hello, File!"写入文件中,接着修改example.txt文件的权限为0644,最后删除example.txt文件和example_dir目录。
# 6. 错误处理和异常情况
在文件操作过程中,可能会遇到一些异常情况,如文件不存在、文件读写错误等。为了正确处理这些异常情况,我们需要了解错误码和错误处理函数,并制定相应的异常处理策略。
#### 6.1 文件操作中可能遇到的异常情况
在进行文件操作时,可能会遇到以下几种异常情况:
1. 文件不存在:当试图打开一个不存在的文件时,会导致文件打开失败。
2. 文件读写错误:当读取或写入文件时,可能会发生读写错误,例如文件已满、磁盘空间不足等。
3. 文件权限问题:某些操作需要特定的文件权限才能进行,如果权限不足,将会导致操作失败。
#### 6.2 错误码和错误处理函数
在C语言中,文件操作函数会返回一个错误码来表示操作是否成功。一般情况下,返回0表示操作成功,其他非零值表示操作失败。
此外,C标准库中还提供了一些用于处理错误的函数,例如perror和int strerror(int errnum)。perror函数用于输出错误信息,strerror函数通过错误码获取错误描述信息。
#### 6.3 异常情况的处理策略
在处理文件操作中的异常情况时,可以采取以下策略:
1. 检查文件是否存在:可以使用文件操作函数的返回值来判断文件是否存在,若不存在,可以进行相应的处理,如创建新文件、提示用户文件不存在等。
2. 错误处理函数:在进行文件操作时,要检查返回的错误码,并根据需要进行相应的错误处理。
3. 异常处理机制:对于一些无法预知的异常情况,可以使用异常处理机制,即使用try-catch语句块来捕获异常并进行相应处理。
#### 6.4 实例演示:错误处理和异常情况
```c
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file;
char filename[20];
printf("请输入文件名:");
scanf("%s", filename);
file = fopen(filename, "r");
if (file == NULL) {
perror("文件打开失败");
exit(1);
}
// 读取文件内容并进行相应处理
fclose(file);
return 0;
}
```
在上述示例中,我们首先尝试打开用户输入的文件,如果文件打开失败,将会使用perror函数输出错误信息,然后通过exit函数退出程序。
以上是关于C语言文件操作技术指南的第六章节,我们学习了文件操作中可能遇到的异常情况、错误码和错误处理函数的使用方法,以及异常情况的处理策略。希望通过本章的学习,能够帮助你更好地进行文件操作并处理异常情况。
0
0