不带缓存的I/O操作
- 即底层操作,文件底层I/O操作的系统调用主要有open、 close、read、write、lseek函数来直接操作文件。
函数 | 作用 |
open | 打开或创建文件 |
close | 关闭文件 |
read | read 从指定的文件描述符中读出的数据放到缓冲区中,并返回实际读出的字节数。 |
write | 把指定缓冲区的数据写入指定的文件描述符中,并返回实际写入的字节数。 |
lseek | 在指定的文件描述符中将文件指针定位到相应的位置。 |
带缓存的I/O操作
- 带缓冲的I/O操作是基于流缓冲的,是符合ANSI C的标 准I/O处理。比如:printf()、scanf()函数等。
- 带缓冲的I/O操作是在内存中开辟一个“缓冲区”,为 程序中的每一个文件使用。当执行读文件的操作时,从 磁盘文件中将数据先读入内存“缓冲区”,装满后再从 内存“缓冲区”依次读入接收的数据。
函数 | 作用 |
fopen | 打开或创建文件 |
fclose | 关闭文件 |
fread | 从文件中读取一个字节。 |
fwrite | 将数据成块写入文件流 |
fseek | 移动文件流的读写位置。 |
ftell | 查询文件流当前的读写位置。 |
rewind | 把文件的读写位置设置在文件头。 |
fgetc | 从文本文件中读取一个字符。 |
fputc | 向文本文件中写入一个字符。 |
fgets | 从文本文件中读取一个字符串(一行数据,以\n结尾) |
fputs | 向文本文件中写入一个字符串 |
根据文件要求需要有一个源文件src_file,这边用python创建一个dest_file:
python代码:
import random
file = open("./src_file.txt", "w+", encoding="utf-8")
n = 0
filelist = {}
lens = 0
while (n < 999):
for i in range(8):
file.write(chr(random.randint(97 - 24, 97 + 24)))
file.write(':')
for i in range(27):
file.write(chr(random.randint(97 - 24, 97 + 24)))
# file.write("\n")
n = n + 1
file.write("\n")
生成的文件是这样的,用冒号前面8位作为用户名
(1) 实训1:文件内容拷贝
程序功能: 设计程序,要求从一源文件src_file(若不存在则创建) 中读取倒数第二个10KB数据复制到目标文件dest_file。
如果在linux下,如下编译执行c文件
gcc m1.c -o m1.o
./m1.o
代码:
#include <stdio.h>
#define OFFSET 10*1024
int main() {
char *dw = "./dest_file.txt";
char *df = "./src_file.txt";
char File_fread[OFFSET];
FILE *fp = fopen(df, "r");
FILE *fp_wt = fopen(dw, "w");
// 读取位置定位到距离文件末尾倒数第二个10KB的起始位置
fseek(fp, -OFFSET * 2, SEEK_END );
// 写入10KB数据
fread(File_fread, OFFSET, 1, fp);
fwrite(File_fread, sizeof(File_fread), 1, fp_wt);
fclose(fp);
return 0;}
得到结果10240字节:
(2) 实训2:字符串文件内容解析
程序功能: 通过系统文件/etc/passwd,解析本系统共计有哪些用户,并把所有用户的用户名写入本地文件test5中。
根据文本格式,我们用冒号前面8位作为用户名
代码:
#include <stdio.h>
#define OFFSET 10*1024
int main() {
char *dw = "./src_file_user.txt";
char *df = "./src_file.txt";
char File_fread[OFFSET];
FILE *fp = fopen(df, "r");
FILE *fp_wt = fopen(dw, "w");
int n = 0;
while (n <= OFFSET) {
if (fgetc(fp) == ':') {
fseek(fp, -9, SEEK_CUR);
fread(File_fread, 8, 1, fp);
fwrite(File_fread, 8, 1, fp_wt);
fwrite("\n", 1, 1, fp_wt);
// 偏移回去并且跳过字符 `:`
fseek(fp, 10, SEEK_CUR);
}
n++;
}
return 0;}
得出结果:
至此要求完成,可以根据自己情况进行修改代码