日期:2014-05-16  浏览次数:20827 次

Linux下文件I/O操作详解

Linux下文件I/O操作详解
2010年12月26日
  1. 文件I/O操作类型
  文件在Linux系统中是一个广泛的概念,Linux将所有的硬件设备当作文件来处理。文件的I/O分为两种类型,第一种类型是非缓冲式文件操作,主要是由系统调用提供,另一种是缓冲式I/O操作,主要是由C语言的标准输入输出库函数提供。
  2. 非缓冲式文件I/O操作
  非缓冲式文件操作对于小规模文件的读写,或者是实时设备,执行非缓冲式文件操作,应用程序能够立即得到数据。非缓冲式文件操作的函数主要是由系统调用提供,有以下几个函数,read(),write(),lseek().
  文件标识符是一个整数,系统预留了3个文件标识符:
  0  代表标准输入,即通过键盘输入
  1  代表标准输出,即输出到终端
  2 标准错误,系统中存放错误信息的堆栈
  read(文件标识符,内存指针,内存块长度)
  作用: 从文件中把数据读入到内存块中。
  返回值: read函数的返回值是读取数据的长度。如果返回0,表示没有读任何数据,如果返回1,表示运行时错误。
  write(文件标识符,内存指针,内存块长度)
  作用: 将指定长度的数据写入到文件中去。
  返回值: write函数返回j是实际写入文件中的数据长度。如果返回0,表示没有写任何数据,如果返回1,表示运行时错误。
  lseek(文件标识符,偏移长度,起始位置)
  作用: 用来设置读写指针的位置
  起始位置有三个宏: SEEK_SET,SEEK_CUR,SEEK_END,分别是以文件开始位置,当前位置,文件尾为参考位置进行偏移。
  非缓冲式文件操作程序:
  用到的函数有open,read,write,close,这些都是系统调用提供的函数。
  /**
  文件的输入输出操作是对设备进行操作的基础
  第一部分是非缓冲性文件操作,这种操作适合于小规模文件的读写和对实时性要求比较高的文件的读写,这类操作是系统调用提供的
  第二部分是缓冲性文件操作,所面向的则是大规模非实时性数据处理问题,这类操作是标准输入输出库提供的
  非缓冲性文件操作函数只有两个,read()和write()函数,这些函数通过文件标识符找到文件
  有3个系统预定义的文件标识符
  0标准输入,即通过终端输入
  1标准输出,即通过终端输出
  2标准错误 ,系统存放错误信息的堆栈
  read(文件标识符,内存块指针,内存块长度);//从文件中读取数据保存到内存块中,返回实际读取的长度,如果返回值是0,表明没有读取任何数据,运行错误时返回1
  write(文件标识符,内存块指针,内存块长度);//将指定的数据写入到文件中去,返回实际写入的长度,返回值为0,表明没有写入任何数据,运行错误时返回1
  lseek(文件标识符,偏移长度,起始位置);//用来指定读写指针的具体位置 SEEK_SET以开始 位置为参考坐标,将指针设置到偏移位置上, SEEK_CUR以当前位置为参考位置,将指针设置到偏移位置上 SEEK_END 以结束位置为参考位置,将指针设置到偏移位置上,SEEK_CUR,SEEK_END时,指针偏移位置可以是负值,表示向前偏移
  **/
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  #define LENGTH 20000 
  void read1(const char* f_path);
  void write1(const char* fsrc_path,const char* fdes_path);
  int main(){
  const char* fsrc_path="/etc/passwd";
  const char* fdes_path="test.txt";
  read1(fsrc_path);//读取内容输出到终端
  write1(fsrc_path,fdes_path);//将读取的内容保存到指定的文件中去
  read1(fdes_path);//再将写入文件显示到终端上 
  return 0;
  }
  void read1(const char* f_path){//读取文件的内容到内存块上,并输出显示到终端上
  int real=0;//定义实际读取的字节数
  int i=0;
  int f;//定义文件标识符
  char c[LENGTH];
  f=open(f_path,O_RDONLY);//以只读的方式读文件
  if(f!=-1){
  real=read(f,c,LENGTH);//第一个参数是文件描述符,第二个参数是内存块指针,第三个参数是内存块长度
  if(real>0){
  for(;real>0;real--){
  printf("%c",c[i++]);//打印到终端
  }
  }
  else{
  perror("读取错误");
  }
  }
  else {
  perror("文件打开错误");
  }
  }
  void write1(const char* fsrc_path,const char* fdes_path){//将从文件fsrc_path读出的内容写入到文件fdes_path中去
  int fdes;//目标文件的文件描述符
  int fsrc;//源文件的文件描述符
  int realread=0;//实际从文件读取的字节数
  int realwrite=0;//实际写入到文件的字节数
  int i=0;
  char c[LENGTH];//定义内存块指针
  fdes=open(fdes_path,O_RDWR);
  if(fdes==-1){
  fdes=open(fdes_path,O_RDWR|O_CREAT,0664);//如果目标文件不存在,则建立一个目标文件
  }
  fsrc=open(fsrc_path,O_RDONLY);
  if(fsrc!=-1){
  realread=read(fsrc,c,LENGTH);
  if(realread>0){
  write(fdes,"123",3);
  lseek(fdes,0,SEEK_CUR);//将指针移动到文件的第2个字符上进行写
  realwrite=write(fdes,c,realread);
  if(realwrite==realread){
  printf("%s\n","写入文件成功");
  }
  else{
  perror("写入失败");
  }
  close(fdes);
  close(fsrc);
  }
  else{
  perror("读取错误");
  }
  }
  else{
  perror("文件打开错误");
  }
  }
  read1()函数的功能是读取文件的内容显示到终端。
  write1()将从源文件中读取的内容写到目的文件中去,可以实现文件的复制。
  3. 缓冲式文件I/O操作
  (1) 缓冲区是为程序分配的内存块,在进行数据比较大且不要求实时性的I/O操作时,一部分数据被放于缓冲区中,只有当数据块的长度要超过缓冲区的长度或时间周期到达时,才把这些数据送到指定的位置。基于缓冲区的设备操作是为了减少读写的次数,从而减小系统开销,主要适用于大量数据的读写操作。
  这部分函数是由标准输入输出提供的,即stdio. 用FILE*结构体指针作为文件流指针标识,同时系统预定