但简单来讲在Linux中两者区别:标准IO简单来说就是打开文件所使用的指针是文件指针,系统IO函数就是使用的文件描述符。
文件指针通常封装了文件描述符。在许多编程语言和操作系统中,文件指针是一种高级抽象,用于对文件进行读写操作,并且通常会与文件描述符相关联。
文件描述符是操作系统内部用于标识打开文件的整数值。每个打开的文件都会被分配一个唯一的文件描述符。文件描述符可以看作是一个索引,它允许操作系统快速定位到相应的文件。
文件指针是一种更高级别的概念,它通常由编程语言或库提供,用于方便地对文件进行读写操作。文件指针封装了文件描述符,并提供了更多的文件操作功能,如文件读取、写入、定位、关闭等。
例如,在C语言中,FILE
结构表示文件指针,它封装了文件描述符,并提供了一系列文件操作函数,如fopen
、fclose
、fread
、fwrite
等,使得文件操作更加方便和易于管理。
总之,文件指针是对文件描述符的抽象和封装,它提供了更高级别的接口,以便程序员更轻松地进行文件操作。文件指针通常是编程语言或库提供的,并用于文件的高级I/O操作。
-
文件流(File Stream): 文件流是一个更抽象的概念,通常指的是通过标准I/O库提供的高级文件处理机制。文件流是通过一个结构体指针(
FILE*
)来表示的,这个结构体通常包含了文件的一些属性和状态信息,如文件位置指针、缓冲区等。文件流提供了一种高级接口,方便进行文件的读写操作。在C语言中,使用fopen
函数创建文件流,然后使用相关的文件操作函数(如fprintf
、fscanf
、fclose
等)来进行文件操作。 -
文件指针(File Pointer): 文件指针是指向文件流的指针,通常是一个
FILE*
类型的指针。文件指针指向文件流的起始位置,通过移动文件指针,可以在文件中定位到不同的位置,进行读写操作。在上述的例子中,file
就是一个文件指针
(1)标准C库I/O函数在读写的时候,中间有一个缓冲区,而在Linux系统中,底层的系统调用(system calls)并不直接使用标准C库的缓冲机制,而是通过一些系统级别的缓冲区来进行I/O操作。Linux提供了一种称为"buffered I/O"(缓冲I/O)的机制,通过在内核中使用缓冲区来优化读写操作。这使得在用户空间的应用程序调用系统调用时,实际的I/O操作可能并不是立即发生的。;如果中间有缓冲区的话在进行读写操作的时候会先存到缓冲区,再刷新到磁盘,它比直接逐条读写到磁盘效率要高。
(2)根据应用场景选择合适的I/O函数,如:再进行网络通信时就应该使用Linux系统I/O函数,因为通信更要求实时性;而在对磁盘进行读写时则选择标准C库I/O函数。特别利用标准IO函数与套接字缓冲进行数据交换就能够体现出来。
C库的I/O函数:
FIFE *fopen(const char *path, const char *mode);
/*
path: 打开文件路径
mode: 打开文件模式
*/
int fclose(FIFE *stream)
// 关闭当前文件流
int fgetc(FIFE *stream)
// 读取一个字符,返回该字符转换为int类型的值
int fputc(int c, FIFE *stream);
// 把c转换为对应的字符,写到stream里
char *fgets(char *s, int size, FIFE *stream);
// 读到换行符或者EOF截止,结果保存到s中,会多保存一个'\0'
int fputs(const char *s, FIFE *stream);
// 把s除去'\0'之外的字符写到stream里
size_t fread(void *ptr, size_t size, size_t nmemb, FIFE *stream);
// 读nmemb个元素,每个大小size字节,保存到ptr里
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FIFE *stream);
// 写nmemb个元素,每个大小size字节,写到stream里
// 文件位置指针相关:
int fseek(FIFE *stream, long offset, int whence)
long ftell(FIFE *stream)
void rewind(FIFE *stream)
int fflush(FIFE *stream)
// printf/scanf一族
int printf(const char *format);
int fprintf(FIFE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...); //可以看成是atoi的反向函数
//sprintf()可能会造成缓冲区溢出
int snprintf(char *str, size_t size, const char *format, ...);
int scanf(const char *format, ...);\
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char* format, ...);
linux系统I/O:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int close(int fd);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
off_t lseek(int fd, off_t offset, int whence);
标准C库(也称为C标准库)和Linux系统提供的IO函数在很多方面都有相似之处,但也存在一些重要的区别。下面是它们之间的比较:
-
跨平台性:
- 标准C库IO函数:这些函数是跨平台的,因为它们是C语言的一部分,可以在不同的操作系统上使用。
- Linux系统IO函数:这些函数通常是特定于Linux的,因此不能直接在其他操作系统上使用。Linux的IO函数通常包含在Linux内核中,而不是C语言标准库中。
-
函数名称:
- 标准C库IO函数:标准C库提供了一组IO函数,例如
printf
、scanf
、fopen
、fclose
等,它们使用较为常见的命名约定。 - Linux系统IO函数:Linux系统提供了一组与系统调用相关的IO函数,如
open
、read
、write
、close
等。这些函数的命名更直接地反映了它们的底层操作。
- 标准C库IO函数:标准C库提供了一组IO函数,例如
-
功能:
- 标准C库IO函数:标准C库提供了更高级别的IO函数,例如
printf
和scanf
,它们提供了格式化输入输出的功能,更易于使用。同时,C库还提供了文件流的概念,可以通过FILE
指针进行文件操作。 - Linux系统IO函数:Linux系统IO函数更接近底层,可以直接控制文件描述符(File Descriptor)进行IO操作。这使得它们更为灵活,但也更复杂,需要更多的手动管理。
- 标准C库IO函数:标准C库提供了更高级别的IO函数,例如
-
性能:
- 标准C库IO函数:由于提供了更高级别的抽象和缓冲,标准C库IO函数通常在性能上稍逊一筹,特别是对于大量数据的IO操作。
- Linux系统IO函数:Linux系统IO函数更接近硬件,因此在某些情况下可以实现更高的性能。这些函数适用于需要进行精细控制或高性能IO操作的场景。
-
错误处理:
- 标准C库IO函数:通常使用返回值或设置全局
errno
变量来指示错误,并提供了一些函数如perror
来方便错误处理。 - Linux系统IO函数:这些函数通常返回-1以指示错误,并设置全局
errno
变量。错误处理更为直接,需要更多的手动干预。
- 标准C库IO函数:通常使用返回值或设置全局
综上所述,标准C库IO函数适用于跨平台开发和通用目的,提供了更高级别的抽象和易用性。而Linux系统IO函数更适用于需要更底层控制或追求性能的情况,但也需要更多的代码编写和错误处理。选择哪种函数取决于你的具体需求和项目要求。在Linux系统上,根据情况选择使用两者之一或混合使用,根据需要在高级别和底层IO之间切换。