您的位置:首页 > 理论基础 > 计算机网络

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

2017-02-14 16:09 78 查看
什么是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>
4000

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.csdn.net/nk_test/article/details/48215061
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: