Unix网络编程--文件IO(1) 基本API

本文详细介绍了计算机中的输入/输出(I/O)操作概念,包括高级I/O与低级I/O的区别,文件描述符及其作用,以及如何使用C语言进行文件操作的基本API,如open/fopen、close/fclose、read/fread等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是I/O
输入/输出是内存和外设之间拷贝数据的过程:
设备->内存: 输入操作
内存->设备: 输出操作
高级I/O: ANSI C提供的标准I/O库函数成为高级I/O, 也称为带缓冲的I/O;
低级I/O: Linux 提供的系统调用, 通常也称为不带缓冲的I/O;

文件描述符
在网络编程中,我们经常会得到监听套接字描述符已连接套接字描述符。而当我们打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。一个进程启动时,默认打开了3个文件,标准输入、标准输出、标准错误,对应的文件描述符是0(STDIN_FILENO)、1(STDOUT_FILENO)、2(STDERR_FILENO),这些常量定义在unistd.h头文件中。注:括号内的就代表文件指针File*。
文件描述符和文件指针的转换函数:

fileno: 将文件指针转换成文件描述符

int fileno(FILE *stream);

fdopen: 将文件描述符转换成文件指针

FILE *fdopen(int fd, const char *mode);
int main()  
{  
    printf("fileno(stdin)= %d\n",fileno(stdin));  
    /*fileno(stdin)=0*/  
}   

基本API

基本API,就是要从最基本的说起,现在我们先来明白freadread的区别:
fread返回的是一个FILE结构指针,而read返回的是一个int的文件描述符,前者fopen/fread的实现是靠调用底层的open/read来实现的.

fopen/fread
是C标准的库函数,操作的对象是:file stream

open/read
是和操作系统有关的系统调用。操作的对象是:file descriptor

简单一点说,f是ANSI的C标准库,后面的是UNIX下的系统调用,如果要和底层硬件打交道,必须是后面的!

1.open/fopen
打开成功返回文件描述符;打开失败返回-1。
int open(const char *pathname, int flags);

pathname: 文件名, 可以包含[绝对/相对]路径名;
flags: 文件打开模式

这里写图片描述

#include <sys/stat.h> 
#include <fcntl.h> // 包含close所需要的头文件 
#include <unistd.h> 
int main(int argc, char *args[]) { 
// 以只读方式打开一个存在的文件 
   int fd1 = open("a.txt", O_RDONLY); 
   printf("fd1 = %d\n", fd1); 
   close(fd1);
   // 以只读方式打开一个不存在的文件 
   int fd2 = open("b.txt", O_RDONLY); 
   printf("fd2 = %d\n", fd2);
   close(fd2); return 0; 
 }

notes:fd1的值为-1,fd2的值为3,由于文件描述符0、1、2已经默认存在了,因此,新打开的文件的文件描述符是从3开始的。

#include<stdio.h>
FILE * fopen(const char * path,const char * mode);
/*文件顺利打开后,指向该流的文件指针就会被返回。若果文件打开失败则返回NULL,并将错误代码存在error中*/

2.close/fclose

int close(int fd);

关闭文件描述符, 使得文件描述符得以重新利用,一个进程结束时也会主动关闭所有的文件。

int fclose(FILE * stream);

fclose()用来关闭先前fopen()打开的文件。此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源。

3.read/fread

ssize_t read(int fd, void *buf, size_t count);
/*ssize_t 是int型(无符号整型),占4个字节,在64位计算机系统中,ssize_t是long int 型,占8个字节*/

返回从文件复制到缓冲区的字节数,count:从该文件复制到buf的字节个数。

ssize_t fread(void * ptr,ssize_t size,ssize_t count,FILE * stream);
/*fread() 用来从文件流中读取数据,返回实际读取到的count数目*/

stream:已打开的文件指针
ptr:指向欲存放读取进来的数据空间,读取的字符数以参数size*count来决定

4.wirte/fwrite

ssize_t write(int fd, const void *buf, size_t count);  
/*write返回大于0时, 并不代表buf的内容已经写入到磁盘上的文件中了, 其仅仅代表buf中的数据已经copy到相应的内核缓冲区高速缓冲*/
ssize_t fwrite(const void * ptr,size_t size,size_t count,FILE * stream);

5.iseek/fseek

off_t lseek(int fd, off_t offset, int whence); 
/*off_t是一个long的类型别名*/
int fseek(FILE *stream, long offset, int fromwhere);
/*fseek 用于二进制方式打开的文件,移动文件读写指针位置*/

stream为文件指针;offset为偏移量,整数表示正向偏移,负数表示负向偏移;origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2:
fseek(fp,100L,0):把fp指针移动到离文件开头100字节处;
fseek(fp,100L,1):把fp指针移动到离文件当前位置100字节处;
fseek(fp,100L,2):把fp指针退回到离文件结尾100字节处。

参考博文:
http://www.cnblogs.com/liuliunumberone/archive/2011/05/06/2038628.html
http://blog.youkuaiyun.com/nk_test/article/details/48215061

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值