一.标准IO和文件IO的区别
(1)一般标准IO指的是C语言的IO操作,文件IO一般指的是Linux系统调用的IO操作。标准O因为是C语言提供的标准库,所以可以在其他操作系统平台编译后可以执行,但是文件IO只能在Linux下使用,标准IO意味着可以在多个平台移植使用。
(2)Linux的IO操作是基于文件描述符的。文件描述符是一个非负整数,用于标识打开或创建的文件。Linux提供了几个系统调用函数来进行IO操作,如open、read、write、close等。
文件的打开通过open函数完成,它返回一个文件描述符。读取文件内容使用read函数,它接受文件描述符、缓冲区地址和读取字节数作为参数,并返回实际读取的字节数。写入文件内容使用write函数,它接受文件描述符、缓冲区地址和写入字节数作为参数,并返回实际写入的字节数。关闭文件使用close函数,它接受文件描述符作为参数。
(3)C语言的IO操作是基于文件指针的。文件指针是一个指向FILE结构体的指针,该结构体描述了文件的属性和缓冲区等信息。C语言提供了一些库函数来进行IO操作,如fopen、fread、fwrite、fclose等。
文件的打开通过fopen函数完成,它返回一个文件指针。读取文件内容使用fread函数,它接受文件指针、缓冲区地址、每个元素的大小和读取元素的个数作为参数,并返回实际读取的元素个数。写入文件内容使用fwrite函数,它接受文件指针、缓冲区地址、每个元素的大小和写入元素的个数作为参数,并返回实际写入的元素个数。关闭文件使用fclose函数,它接受文件指针作为参数。
(4)标准IO和文件IO都可以用来访问文件,那么他们之间有什么区别呢?
通过文件IO读写文件时,每次操作都会执行相关系统调用。这样处理的好处是可以直接读写实际文件,坏处是频繁地系统调用会增加系统开销;而标准IO可以看做是在文件IO的基础上封装了缓冲机制,先读写缓冲区,必要时再访问实际文件,从而减少系统调用次数。
文件IO中用文件描述符表示一个打开的文件,可以访问不同类型的文件(如普通文件、设备文件和管道文件)。而标准IO中用FILE(流)表示一个打开的文件,通常只用来访问普通文件
总的来说,Linux的IO操作是底层的系统调用函数,而C语言的IO操作是基于库函数的高层封装。两者都可以用来进行文件的读写操作,但使用的方式和函数有所不同。
二.标准IO
标准IO库提供了一系列函数,用于对标准输入、输出、错误流以及文件进行操作。这些函数通常在 <stdio.h>
头文件中声明。下面是一些常用的标准IO函数以及它们的功能:
-
fopen() 函数:
#include <stdio.h> FILE *fopen(const char *pathname, const char *mode);
参数:
pathname:文件路径名。
mode:文件打开模式,可以取以下值:
"r":只读模式打开文件。
"w":只写模式打开文件,如果文件不存在则创建文件,如果文件已存在则清空文件。
"a":追加模式打开文件,如果文件不存在则创建文件。
"r+":读写模式打开文件。
"w+":读写模式打开文件,如果文件不存在则创建文件,如果文件已存在则清空文件。
"a+":读写模式打开文件,如果文件不存在则创建文件,并在文件末尾追加数据。
更多模式可以查阅相关文档。
返回值:返回一个文件指针(FILE *),用于后续的文件操作。如果打开文件失败,返回 NULL,并设置 errno 来指示错误原因。
常见用法:用于打开文件,获取文件指针,以便后续的文件操作。 -
fclose() 函数:
#include <stdio.h> int fclose(FILE *stream); 参数: stream:文件指针,需要关闭的文件。 返回值:返回 0 表示成功关闭文件,返回 EOF 表示失败,并设置 errno 来指示错误原因。 常见用法:用于关闭一个已经打开的文件。
-
fread() 函数:
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
ptr:指向存储读取数据的缓冲区。
size:每个数据项的大小(以字节为单位)。
nmemb:要读取的数据项的数量。
stream:文件指针,指向要读取数据的文件。
返回值:返回实际读取的数据项数量,如果到达文件末尾或出错返回值小于 nmemb,同时设置 errno 来指示错误原因。
常见用法:用于从文件中读取数据。 -
fwrite() 函数:
#include <stdio.h> size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
ptr:指向要写入数据的缓冲区。
size:每个数据项的大小(以字节为单位)。
nmemb:要写入的数据项的数量。
stream:文件指针,指向要写入数据的文件。
返回值:返回实际写入的数据项数量,如果出错返回值小于 nmemb,同时设置 errno 来指示错误原因。
常见用法:用于向文件中写入数据。 -
fseek() 函数:
#include <stdio.h> int fseek(FILE *stream, long offset, int whence); 参数: stream:文件指针,指向要定位的文件。 offset:偏移量。 whence:偏移起始位置,可以取以下值: SEEK_SET:文件开头。 SEEK_CUR:当前文件位置。 SEEK_END:文件末尾。 返回值:返回 0 表示成功,返回非 0 表示失败,并设置 errno 来指示错误原因。 常见用法:用于在文件中移动文件指针。
#include <stdio.h>
int main()
{
FILE *fp;
char buffer[100];
// 打开一个文件来写入数据
fp = fopen("example.txt", "w");
if (fp == NULL)
{
printf("无法打开文件\n");
return 1;
}
fprintf(fp, "这是一个用于示例的文件\n");
fclose(fp);
// 打开文件来读取数据
fp = fopen("example.txt", "r");
if (fp == NULL)
{
printf("无法打开文件\n");
return 1;
}
fgets(buffer, 100, fp);
printf("读取的内容: %s", buffer);
fclose(fp);
return 0;
}
执行结果:
这是一个用于示例的文件
三.文件IO
在Linux系统中,文件I/O操作通常使用系统调用来实现。下面是一些常见的Linux文件I/O系统调用以及它们的功能:
好的,我会重新整理一下,详细说明每个函数的参数、返回值以及常见用法:
-
open() 函数:
#include <fcntl.h> int open(const char *pathname, int flags, mode_t mode); 参数: pathname:文件路径名。 flags:文件打开标志,可以取以下值的组合: O_RDONLY:只读模式打开文件。 O_WRONLY:只写模式打开文件。 O_RDWR:读写模式打开文件。 O_CREAT:如果文件不存在,则创建文件。 O_TRUNC:如果文件存在且为只写或读写打开,则将文件长度截断为 0,即清空文件内 容。 O_APPEND:在文件末尾追加数据。 等等,还有其他的标志,可根据需要组合使用。 mode:文件权限,仅在 O_CREAT 标志被设置时有效,通常为八进制数。 返回值:返回一个新的文件描述符(非负整数),如果打开文件失败,返回 -1,并设置 errno 来指示错误原因。 常见用法:用于打开文件,获取文件描述符,以便后续的文件操作。
-
close() 函数:
#include <unistd.h> int close(int fd); 参数: fd:文件描述符,需要关闭的文件。 返回值:返回 0 表示成功关闭文件,返回 -1 表示失败,并设置 errno 来指示错误原因。 常见用法:用于关闭一个已经打开的文件。
-
read() 函数:
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); 参数: fd:文件描述符。 buf:用于存放读取数据的缓冲区。 count:要读取的字节数。 返回值:返回实际读取的字节数,如果到达文件末尾返回 0,出错返回 -1,并设置 errno 来指示错误原因。 常见用法:用于从文件中读取数据。
-
write() 函数:
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);
-
参数:
fd
:文件描述符。buf
:要写入的数据。count
:要写入的字节数。
-
返回值:返回实际写入的字节数,出错返回 -1,并设置
errno
来指示错误原因。 -
常见用法:用于向文件中写入数据。
-
-
lseek() 函数:
#include <unistd.h> off_t lseek(int fd, off_t offset, int whence); 参数: fd:文件描述符。 offset:偏移量。 whence:偏移起始位置,可以取以下值: SEEK_SET:文件开头。 SEEK_CUR:当前文件位置。 SEEK_END:文件末尾。 返回值:返回新的文件偏移量(以字节为单位),出错返回 -1,并设置 errno 来指示错误原因。 常见用法:用于在文件中移动文件指针。
-
fcntl() 函数:
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );参数:
fd:文件描述符。
cmd:操作指令,可以取以下值:F_SETFD:设置文件描述符标志。
F_GETFD:获取文件描述符标志。
F_SETFL:设置文件状态标志。
F_GETFL:获取文件状态标志。
F_DUPFD:复制文件描述符。
返回值:根据操作指令的不同有不同的含义,出错返回 -1,并设置 errno 来指示错误原因。
常见用法:用于对文件描述符进行各种控制操作,如设置文件状态标志、获取文件状态标志等。
如果 cmd 参数需要额外的参数,则需要将其作为可变参数传递给 fcntl() 函数。等等,还有其他的操作指令,具体可以查阅相关文档
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BUFFER_SIZE 1024
int main() {
int fd;
char buffer_write[BUFFER_SIZE];
char buffer_read[BUFFER_SIZE];
ssize_t bytes_read;
// 创建一个示例文件并写入内容
fd = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
{
perror("无法创建文件");
return 1;
}
strcpy(buffer_write,"这是一个示例文件");
write(fd, buffer_write, strlen(buffer_write));
close(fd);
// 打开文件来读取数据
fd = open("example.txt", O_RDONLY);
if (fd == -1)
{
perror("无法打开文件");
return 1;
}
// 逐步读取文件内容
while ((bytes_read = read(fd, buffer_read, BUFFER_SIZE)) > 0)
{
write(STDOUT_FILENO, buffer_read, bytes_read); // 将读取的内容直接写入标准输出
}
if (bytes_read == -1)
{
perror("读取文件失败");
close(fd);
return 1;
}
// 关闭文件
close(fd);
return 0;
}
执行结果:
这是一个示例文件