文件IO总结

本文详细介绍了Linux系统中的系统IO操作,包括open、close、read、write、lseek等函数的使用,以及文件描述符和文件权限的概念。同时,对比了标准IO操作,如fopen、fclose、fread、fwrite、fseek等,并演示了如何进行文件读写、位置移动等。此外,还涉及到文件属性的检查和目录操作。最后,提到了LCD屏幕的图像刷图方法和TS触摸屏的点击与滑动事件处理。

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

系统IO

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname,int flags);
int open(const char *pathname, int flags, mode_t mode);
参数:
    pathname:要打开的文件名

    flag:O_RDONLY:只读方式打开文件
        O_WRONLY:只写方式打开文件
        O_RDWR:读\写方式打开文件
        (O_RDONLY、O_WRONLY、O_RDWR    这三个参数互斥)
        O_CREAT:如果文件不存在,则创建新文件
        O_EXCL:如果使用O_CREAT选项且文件存在,则返回错误信息
        O_APPEND:以追加方式打开文件
        O_TRUNC:如果文件已经存在,则删除文件中原有数据
        O_NOCTTY:如果文件为终端,那么终端不可以作为调用open()系统调用的那个进程的控制终端

    mode:如果文件被新建,指定其权限为mode(八进制表示法)
        一般为0664或0775等
返回值:
    成功:大于或等于0的整数(文件描述符)
    失败:-1

#include <unistd.h>
int close(int fd);
参数:
    fd:文件描述符
返回值:
    成功:0
    失败:-1

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
参数:
    fd:文件描述符
    buf:指向存放读到的数据的缓冲区
    count:想要读取的字节数
返回值:
    成功:实际读到的字节数
    失败:-1

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
参数:    
    fd:文件描述符
    buf:指向要写入的数据
    count:想要写入的字节数
返回值:
    成功:实际写入的字节数
    失败:-1

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
参数:
    fd:文件描述符
    offset:新位置偏移量相对基准点的偏移
    whence:基准点
        SEEK_SET:文件开头处
        SEEK_CUR:当前位置
        SEEK_END:文件末尾处
返回值:
    成功:新文件位置偏移量
    失败:-1

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数:
    addr:一般为NULL
    length:映射内存大小
    prot:映射内存的保护权限
        PROT_EXEC:可执行
        PROT_READ:可读
        PROT_WRITE:可写
        PROT_NONE:不可访问
    flags:一般都是MAP_SHARED
    fd:文件描述符
    offset:文件映射的开始区域偏移量一般为0

---------------------------------------------------------------------
标准IO

#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
参数:
    path:打开的文件名
    mode:权限
        r:只读方式打开文件,文件必须存在
        r+:读/写方式打开文件,要求文件必须存在
        w:只写方式打开文件,文件如果不存在会创建新文件,如果文件存在会将其内容清空
        w+:读/写方式打开文件,文件如果不存在会创建新文件,如果文件存在会将其内容清空
        a:只写方式打开文件,文件如果不存在会创建新文件,且文件位置偏移量被自动定位到文件末尾(以追加的方式写数据)
        a+:读/写方式打开文件,文件如果不存在会创建新文件,且文件位置偏移量被自动定位到文件末尾(以追加的方式写数据)
返回值:
    成功:文件指针
    失败:NULL

#include <stdio.h>
int fclose(FILE *stream);
参数:
    fp:文件指针
返回值:
    成功:0
    失败:EOF

#include <stdio.h>
int putchar(int c);
int putc(int c, FILE *stream);
int fputc(int c, FILE *stream);
参数:
    c:写入的字符
    stream:写入的文件指针
返回值:
    成功:写入到字符
    失败:EOF
int fputs(const char *s, FILE *stream);
int puts(const char *s);
参数:
    s:自定义缓冲区指针
    stream:写入数据的文件指针
返回值:
    成功:非负整数
    失败:EOF

#include <sys/ioctl.h>
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
    ptr:自定义缓冲区指针
    size:数据块大小
    nmemb:数据块个数
    stream:被读取数据的文件指针
返回值:
    成功:读取数据块个数,等于nmemb
    失败:读取数据块个数,小于nmemb或等于0
当返回值小于nmemb时,文件stream可能达到末尾,或者遇到错误

#include <sys/ioctl.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
参数:
    ptr:自定义缓冲区指针
    size:数据块大小
    nmemb:数据块个数
    stream:被写入数据的文件指针
返回值:
    成功:写入数据块个数,等于nmemb
    失败:写入数据块个数,小于nmemb或等于0

#include <sys/ioctl.h>
int fseek(FILE *stream, long offset, int whence);
参数:
    stream:需要新设置位置偏移量的文件指针
    offset:新位置偏移量相对基准点的偏移
    whence:基准点
        SEEK_SET:文件开头处
        SEEK_CUR:当前位置
        SEEK_END:文件末尾处
返回值:
    成功:0
    失败:-1

#include <sys/ioctl.h>
long ftell(FILE *stream);
参数:
    stream:文件指针
返回值:
    成功:当前偏移量
    失败:-1

#include <sys/ioctl.h>
void rewind(FILE *stream);
参数:
    stream:文件指针
返回值:
    无

#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
参数:
    format:格式控制串(%d %s %c.......)
    s:写入数据的自定义缓冲区
    n:自定义缓冲区的大小
int snprintf(char *str, size_t size, const char *format, ...);
返回值:
    成功:写入的字节数
    失败:-1

#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
参数:
    format:格式控制串(%d %s %c.......)
分割:
    FILE *fp = fopen("2.txt","r+");
    
    char buf1[1024] = {0};
    char buf2[1024] = {0};
    char buf3[1024] = {0};
    
    fscanf(fp,"%[^','],%[^','],%s",buf1,buf2,buf3);
    
    
    printf("buf1:%s\n",buf1);
    printf("buf2:%s\n",buf2);
    printf("buf3:%s\n",buf3);
int sscanf(const char *str, const char *format, ...);

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);
参数:
    pathname:路径名
    buf:存储文件属性的结构体指针
返回值:
    成功:0
    失败:-1
struct stat file_info
stat(path,&file_info);

存储文件属性的结构体信息
           struct stat {
               dev_t     st_dev;         /* ID of device containing file */
               ino_t     st_ino;         /* inode number */
               mode_t    st_mode;        /* protection */     可以判断它的文件属性
               nlink_t   st_nlink;       /* number of hard links */
               uid_t     st_uid;         /* user ID of owner */
               gid_t     st_gid;         /* group ID of owner */
               dev_t     st_rdev;        /* device ID (if special file) */
               off_t     st_size;        /* total size, in bytes */
               blksize_t st_blksize;     /* blocksize for filesystem I/O */
               blkcnt_t  st_blocks;      /* number of 512B blocks allocated */

               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */

               struct timespec st_atim;  /* time of last access */
               struct timespec st_mtim;  /* time of last modification */
               struct timespec st_ctim;  /* time of last status change */

           #define st_atime st_atim.tv_sec      /* Backward compatibility */
           #define st_mtime st_mtim.tv_sec
           #define st_ctime st_ctim.tv_sec
           };

用宏定义来判断文件的属性
           S_ISREG(m)  is it a regular file?//判断是否为普通文件

           S_ISDIR(m)  directory?//判断是否为目录

           S_ISCHR(m)  character device?//判断是否为字符设备文件

           S_ISBLK(m)  block device?//判断是否为块设备文件

           S_ISFIFO(m) FIFO (named pipe)?//判断是否为管道文件

           S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)//判断是否为链接文件

           S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)//判断是否为套接字文件

---------------------------------------------------------------------------------
目录操作

#include <sys/typed.h>
#include <dirent.h>
DIR *opendir(const char *name);
参数:
    name:目录名
返回值:
    成功:目录指针
    失败:NULL

#include <dirent.h>
struct dirent *readdir(DIR *dirp);
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
参数:
    dirp:目录指针
返回值:
    成功:目录指针
    失败:NULL

#include <string.h>
char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);
参数:
    str:需要分割字符串的缓冲区指针
    delim:用于分割的标识标记(符号)

-----------------------------------------------------------------------------------
LCD屏的操作:刷图

    //打开lcd
    int lcd = open("/dev/fb0",O_RDWR);
    if(lcd < 0)
    {
        perror("open error!\n");
        return -1;
    }
    
    //lcd映射
    //指针指向一个像素点
    int *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
    if(p == NULL)
    {
        perror("mmap fail!\n");
        return -1;
    }    
    //打开bmp图片
    int lcd_bmp = open("1.bmp",O_RDWR);
    if(lcd_bmp < 0)
    {
        printf("open bmp fail!\n");
        return -1;
    }
    
    //去除掉头54个字节
    lseek(lcd_bmp,54,SEEK_SET);

    //存储bmp图片的buffer:800*480*3
    char buf[800*480*3] = {0};
    
    //读bmp图片
    read(lcd_bmp,buf,800*480*3);
    
    //将buf数据通过指针p填充到LCD中
    int x;//x表示横轴
    int y;//y表示纵轴
    for(y=0;y<480;y++)
    {
        for(x=0;x<800;x++)
        {
            *(p+(y*800+x)) = buf[3*((479-y)*800+x)] |buf[3*((479-y)*800+x)+1]<<8 |buf[3*((479-y)*800+x)+2]<<16;    
        }
    }

    
    //lcd映射释放
    munmap(p,800*480*4);
    
    //关闭lcd\bmp
    close(lcd);
    close(lcd_bmp);

--------------------------------------------------------------------------------------------------
TS(touch screen)触摸屏的操作:点击、滑动

enum SLIDE{left,right,up,down};
enum TOUCH{left_area,right_area};

int fd;
//获取点击区域位置
int touch()
{
    //定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储到ts中
    struct input_event ts;
    
    //读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)
    int x,y;
    while(1)
    {
        read(fd,&ts,sizeof(struct input_event));
        if(ts.type == EV_ABS && ts.code == ABS_X)
        {
            x = ts.value*800/1024;//x轴坐标
        }
        if(ts.type == EV_ABS && ts.code == ABS_Y)
        {
            y = ts.value*480/600;//y轴坐标
        }
        
        //按下去的时刻或者松手后的时刻
        if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 0)//松手后
        {
            if(x <400)
                return left;
            else
                return right;
        }
    }
}

//拿去上下左右滑动状态
int slide()
{
    //定义一个存储触摸屏信息的结构体,将读取的设备文件信息存储到ts中
    struct input_event ts;
    int x,y,x1,y1;
    
    while(1)
    {
        while(1)
        {
            read(fd,&ts,sizeof(struct input_event));
            if(ts.type == EV_ABS && ts.code == ABS_X)
            {
                x = ts.value*800/1024;
            }
            if(ts.type == EV_ABS && ts.code == ABS_Y)
            {
                y = ts.value*480/600;
            }
            
            //按下去的时刻或者松手后的时刻
            if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 1)//按下去
            {
                printf("按下去 (%d,%d)\n",x,y);
                break;
            }
        }
        
        //读触摸屏信息--阻塞函数(点击触摸屏之后才会往下执行)
        while(1)
        {
            read(fd,&ts,sizeof(struct input_event));
            if(ts.type == EV_ABS && ts.code == ABS_X)
            {
                x1 = ts.value*800/1024;
            }
            if(ts.type == EV_ABS && ts.code == ABS_Y)
            {
                y1 = ts.value*480/600;
            }
            
            if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 0)//松手
            {
                printf("松手后 (%d,%d)\n",x1,y1);
                break;
            }
        }
        
        if(x1-x > 100)
            return right;
        if(x1-x < -100)
            return left;
        if(y1-y > 100)
            return down;
        if(y1-y < -100)
            return up;
    }
    
    return 0;
}

int main(int argc,char *argv[])
{
    //打开触摸屏
    fd = open("/dev/input/event0",O_RDWR);
    if(fd < 0)
    {
        perror("open fd error!\n");
        return 0;
    }
    
    while(1)
    {
        //点击
        switch(touch())
        {
            case left:
                printf("touch left!\n");
                break;
            
            case right:
                printf("touch right!\n");
                break;
        }
        
        //滑动
         switch(slide())
        {
            case up:
                printf("up slide!\n");
                break;
                
            case down:
                printf("down slide!\n");
                break;
            
            case left:
                printf("left slide!\n");
                break;
            
            case right:
                printf("right slide!\n");
                break;
        }
    }
    
    //关闭触摸屏
    close(fd);
    
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值