搜索
简帛阁>技术文章>I/O文件操作

I/O文件操作

一、回顾

之前在C语言中我们也接触到了一些文件操作的函数,因为这些函数都是对流操作的,绝大多数流都是完全缓冲的,读操作和写操作都是在缓冲区进行的,用于输出流的缓冲区只有当被写满的时候才会被舒心到设备或者文件。这样的效率很高。

FILE*fp=fopen(const char*filename,const char*mode);//打开流 filename:文件名  mode:打开的方式
int fclose(FILE*stream)//关闭流
int fgetc(FILE*stream);//字符串输入函数(所有输入流)
int fputc(int c,FILE*stream);//字符串输出函数(所有输出函数)
char*fgets(char*string,int n,FILE *stream)//文本行输入函数  所有输入流
int fputs(const char*string,FILE*stream)//文本行输出流  所有输出流
int fscanf( FILE *stream, const char *format [, argument ]... );//格式化输入函数 所有输入流
int fprintf( FILE *stream, const char *format [, argument ]...);//格式化输出函数  所有输出流
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );//读文件  
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );//写文件

用C语言里面的文件操作函数fopen fscanf实现一个简易版的英语词典,可以帮助记单词的呦!但是首先提前你得自己将单词整理出来写到文件里面,才能从dictionary.txt里面读取向要查看的单词!

 #include<stdio.h>
 #include<stdlib.h>
 #include<string.h>
  typedef struct
  { 
      char yy[50]; 
      char hy[50];
      char cx[6]; 
  }DICT_T;
  DICT_T words[8000];
  int cunt=0; 
  void load_file(void)
  {        
     FILE *fp=fopen("dictionary.txt","r");
    if(fp==NULL)perror("fopen"),exit(1);
      while(!feof(fp)) 
     {
          fscanf(fp,"%s\t%s\t%s",words[cunt].yy,words[cunt].hy,words[cunt].cx);
         cunt++;
      }

     fclose(fp);
  }
 int bin_search(const char*buf)
 {
      int l=0;
     int r=cunt-1;
     while(l<=r)
     {
         int m=l+(r-l)/2;
          if(strcmp(words[m].yy,buf)==0)
         {
             return m;
        }
         else if(strcmp(words[m].yy,buf)<0)
        {
            l=m+1;
         }
         else
        {
            r=m-1;
         }
     }
    return -1;
 }
 int main(void)
 {
    load_file();
    int r;
    char buf[1000];
    do
    {
        printf("please input a word:");
        memset(buf,0x00,sizeof(buf));
        scanf("%s",buf);
       if((r=bin_search(buf))==-1)
      {
            printf("have no this word\n");
        }
         else
        {
           printf("%s :%s %s\n",words[r].yy,words[r].hy,words[r].cx);
        }
     }while(1);
    return 0;
 }

二、Linux的基本I/O函数

在此之前先来认识一下文件描述符。
文件描述符:操作系统通过一个整数代表打开的文件,将这个整数称为文件描述符。
在shell日常操作中,有3个文件描述符是是始终打开的:
- stdin 0 标准输入
- stdout 1 标准输出
- stderr 2 标准错误
文件描述符中所存储的信息:

  • 文件指针
  • 文件的打开次数(引用计数)
  • 文件的磁盘位置
  • 文件的访问权限
    ####打开文件####
int open(const char*path,int flags);
//参数: 
//path:要打开的文件
//flags:要打开的方式
//返回值:
    //成功返回文件描述符
    //失败:返回-1,并将errno置为相应的错误

flags的可能取值:
这里写图片描述

读操作

int read(int fd,char*buff,size_t len);//从文件fd中读取数据到buff所指向的空间,该空间的大小为len
/*
参数:
    buff:用来存放输入数据的内存缓冲区地址,缓冲区至少应该有len个字节,缓冲区的大小至少要比预计读取的最大字符串长度多出1个字节
    len:读取的数据的长度
返回值:
    调用成功返回实际读取的字节数
    遇到文件结束标志返回0
    出现错误返回-1
*/

打开文件/创建文件

int open (const char*path,int flags,mode_t mode);
/*
参数:
    path:要创建的文件名
    mode:权限,会受到默认的umask的影响,mode参数牙可以指定为数字,也可以使用flags的常量区进行逻辑或操作
    flags:O_CREAT | O_RDONLY//创建一个文件只能读
          OCREAT | O_EXECL//O_EXECL只能和CREAT共用   
*/

我们来用一下open函数真切地感受一下它的用法:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
 int main(void)
 {
     int fd=open("open.c",O_RDONLY);
    if(fd==1)
     {
         perror("open");
     }   
     else
    {
        printf("open sucessful\n");
    }   
     while(1)
    {
         char buf[11]={};
         int r=read(fd,buf,10);
         if(r==-1)perror("read"),exit(1);
         if(r==0)
         {
             printf("read over\n");
             break;
        }   
         else
         {
            printf("%s",buf);
            fflush(stdout);
        }
       sleep(1);
     }
    close(fd);
     return 0;
 }

写操作

int write(int fd,const char *buff,size_t len)//向fd所指向的文件中写入数据,数据的起始地址为buff(buff设置为磁盘块的大小读取是最快的),大小为len。
/*
返回值:
    调用成功返回实际写入文件的字节数,该返回值可能小于len参数值,这被称为部分写,对于磁盘来说,造成部分写的原因可能是由于磁盘已满,或是因为进程资源对文件大小的限制
    对于磁盘进行I/O操作时,write()调用成功并不能保证数据已经写入磁盘,因为为了减少磁盘活动量和加快write()系统调用,内核会缓存磁盘的I/O操作。
*/

我们来用一下write函数真切地感受一下它的用法:注意这里这个spider文件要提前创建好,使用touch spider就可以啦!

 #include<string.h>
 #include<stdio.h>
 #include<stdlib.h>
 #include<unistd.h>
 #include<fcntl.h>
int main(void)
  {
     int fd=open("spider",O_CREAT|O_RDWR|O_EXCL,0666);
    if(fd==-1)
     {
         fd=open("spider",O_RDWR);
         if(fd==-1)
            perror("open"),exit(1);
    }
     char*msg="this is mmc";
     int r=write(fd,msg,strlen(msg));
    printf("len=%d,r=%d\n",strlen(msg),r);
     close(fd);
    return 0;
 }

关闭文件

int close(int fd);//close系统调用关闭一个打开的文件描述符,并将其释放回调用进程,供进程继续使用

定位操作

int lseek(int fd,off_t offset,int whence);
/*
参数:
    offset:偏移量
    whence:
        SEEK_SET:将文件偏移量设置为从文件头部起始点开始的offset个字节
        SEEK_CUR:相对于当前文件偏移量,将文件偏移量调整offset个字节
        SEEK_END:将文件偏移量设置为起始于文件尾部的offset个字节
返回值:
    新的相对于文件开头偏移量
    获取文件的大小:lseek(fd,0,END);
*/
  • 文件空洞:
    如果文件的偏移量已经超过了文件的结尾,然后再执行I/O操作,read()调用将会返回0,write()调用可以在文件结尾后的任意位置写入数据。从文件结尾后到新写入数据间的这段空间被称为文件空洞。
  • 注意:

    • 在文件空洞中写入了数据,文件系统才会为之分配磁盘块
    • 空洞的存在意味着一个文件名义上的大小可能要比其占用内存的磁盘存储量大很多,向文件写入字节,内核需要为其分配存储单元,即使文件大小不变,系统的可用磁盘空间也会减少。
    • du:可以查看文件具体占磁盘块的大小,磁盘块是惰性分配的

    文件操作就讲到这里啦!

本文转自实验楼:https://wwwshiyanloucom/courses/24一linuxI/O介绍Linux下一切皆文件,因此文件操作属于Linux下的基本操作。对于用户层来说,所有的操作都是
一、回顾之前在C语言中我们也接触到了一些文件操作的函数,因为这些函数都是对流操作的,绝大多数流都是完全缓冲的,读操作和写操作都是在缓冲区进行的,用于输出流的缓冲区只有当被写满的时候才会被舒心到设备或者
前言I/O操作操作存储器,所以想了解I/O操作,需要了解一点存储器相关知识点。计算机存储器存储器是计算机的核心部件之一,在完全理想的状态下,存储器应该要同时具备以下三种特性:(1)速度足够快:存储器
Lua中I/O库用于读取和处理文件。有两种类型的文件操作,在Lua即隐含文件的描述符和明确的文件描述符。对于下面的例子中,我们将使用一个示例文件testlua,如下图所示。代码如下:sampletes
文件是一些永久存储及具有特定顺序的字节组成的一个有序的,具有名称的集合。与文件有关的概念是目录路径和磁盘存储等。流提供了一种向后备存储写入字节和从后备存储读取字节的方式。后备存储包裹用文件存储或用内存
Java库中使用Path和Files类封装了在用户机器上处理文件系统所需要的所有功能,可以使用Paths来获取一个具体的Path对象,来表示具体的路径。路径Path表示的是一个目录名序列,其后还可以跟
https://blogcsdnnet/deram_boy/article/details/51191425提及这个,就想到了各种文件操作,这种流,什么reader啊,writer啊,buffer啊,
I/O操作文章目录I/O操作一:文件操作1判断文件是否存在2判断是否为文件3创建文件与删除文件4创建目录二:I\O操作1(1)用字节流进行文件写入(OutputStream)1(2)用字符输出流(W
ILE*fopen(constchar*filename,constchar*mode);fopen函数由filename打开,mode参数指定文件的打开方式:'r'只读方式打开,将文件指针指向文件
按照《Unix网络编程》的划分,I/O模型可以分为:阻塞I/O、非阻塞I/OI/O复用、信号驱动I/O和异步I/O,按照POSIX标准来划分只分为两类:同步I/O和异步I/O。一个I/O操作实际上分