直接IO 文件指针偏移函数 文件IO stat

18 篇文章 0 订阅

【1】直接IO (二进制IO)

  1. fread
    int ch[5];
    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    功能:从文件中读按数据类型读去内容(读文件)
    参数:
    ptr:读到的内容存放的地址
    size:读一个对应类型所占空间大小sizeof(short)
    nmemb:读多少个元素
    stream:文件流指针
    返回值:
    成功:读到元素个数
    失败或读到文件结尾:0

  2. fwrite
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    功能:按数据类型将内容写道文件中(写文件)
    参数:
    ptr:写内容存放的地址
    size:写元素类型所占空间大小sizeof(short)
    nmemb:写多少个元素
    stream:文件流指针
    返回值:
    成功:写入元素个数
    失败:0

【2】文件指针偏移函数

  1. int fseek(FILE *stream, long offset, int whence);
    功能:将文件指针偏移到指定的位置
    参数:
    stream:流指针
    offset:偏移量 +1:向后偏移一个位置 -1:向前偏移一个位置
    whence:相对位置
    SEEK_SET:文件开头
    SEEK_CUR:当前位置
    SEEK_END:文件结尾
    返回值:
    成功:0
    失败:-1 更新errno

  2. long ftell(FILE *stream);
    功能:获取当前文件指针的位置
    (计算文件指针从开头到当前位置的长度)
    参数:stream:留置针
    返回值:
    成功:文件指针当前的位置
    失败:-1 更新errno

  3. void rewind(FILE *stream);
    功能:将文件指针定位到文件开头

【3】文件IO

是由posix(可移植操作系统)提供的系统调用函数接口,系统调用基于操作系统,
不同的操作系统向上提供的系统调用函数接口不同。
文件IO是没有缓存机制的,只要进行读写操作就会进行系统调用。
文件IO读写文件是通过文件描述符进行操作
默认情况下,系统已经打开了三个文件描述符:
0、1、2–》标准输入、标准输出、标准出错

文件io可以操作linux下的一切文件类型。

  1. 文件描述符:
    文件描述符是无符号整型的数,它的取值范围是:0~1023,用与去标识打开的一个文件,
    后期对文件的操作均通过操作文件描述符实现。

  2. 文件IO的操作函数
    1)open / close 打开文件/关闭文件
    2)read / write 读文件/写文件
    3)lseek 文件指针偏移函数

  3. open
    #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:打开文件的路径
    flags
    O_RDONLY:只读
    O_WRONLY :只写
    O_RDWR :可读可写
    O_CREAT :文件不存在创建 用到创建:mode 是创建权限 0666
    O_TRUNC :文件存在清空
    O_APPEND : 追加
    mode:文件创建权限
    返回值:成功:文件描述符
    失败:-1,更新errno
    open函数创建出来的文件的权限:
    mode & (~umask)
    umask:权限掩码,用于保护文件
    r:O_RDONLY
    R+:O_RDWR
    w:O_WRONLY | O_CREAT | O_TRUNC,0666
    w+:O_RDWR | O_CREAT | O_TRUNC,0666
    a:O_WRONLY | O_CREAT | O_APPEND,0666
    a+:O_RDWR | O_CREAT | O_APPEND,0666

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

  5. read
    ssize_t read(int fd, void *buf, size_t count);
    功能:读文件
    参数:
    fd:文件描述符
    buf:读到内容存放的位置
    count:期待读取的字符个数
    返回值:
    成功:读到字符个数
    失败:-1 更新errno
    读到文件结尾:0

    注意:read读到的字符串后不自动补\0,并且遇到’\n’会继续往后读。
    期待读多少个字符就会读多少,如果文件中不够,实际又多少读多少个。

    对读到的字符串补’\0’:

    1. 通过read返回的实际读到字符个数,在后边buf[n]=‘\0’;
    2. 用清零函数
      memset
      #include <string.h>
      void *memset(void *s, int c, size_t n);
      s:要清空的首地址
      c:0
      n: 清空字节数
      返回值:清空后空间的首地址

    bzero
    void bzero(void *s, size_t n);
    s:要清空的首地址
    n: 清空字节数

  6. write
    ssize_t write(int fd, const void *buf, size_t count);
    功能:写文件
    参数:fd文件描述符
    buf:写内容的首地址
    count:期待写的字符个数

    返回值:
    成功:实际写入字符的个数
    失败:-1 更新errno
    练习:文件IO实现cp 功能

/*************************************************************************
	> File Name: read.c
	> Created Time: Tue 17 Aug 2021 03:22:53 PM CST
	> Author: noah
 ************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{

	char str[50];
	printf("plz input filename as source\n");
	scanf("%s", str);
	int fd;
	if ((fd = open(str, O_RDONLY)) == -1) {
		perror("source");
		exit(-1);
	}
	char str2[50];
	printf("plz input filename as target\n");
	scanf("%s", str2);
	int fd2;
	if ((fd2 = open(str2, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) {
		perror("target");
		exit(-1);
	}
	char buf[32] = "";
	ssize_t ret;
	while ((ret = read(fd, buf, 32))) {
		write(fd2, buf, ret);
	}
	
	return 0;

}
  1. lseek
    off_t lseek(int fd, off_t offset, int whence);
    功能:将文件指针偏移到指定的位置
    参数:
    fd:文件描述符
    offset:偏移量
    whence:相对位置
    SEEK_SET:文件开头
    SEEK_CUR:当前位置
    SEEK_END:文件结尾
    返回值:
    成功:相对与开头偏移的位置
    失败:-1 更新errno

【4】获取文件属性 stat

  1. int stat(const char *path, struct stat *buf);
    功能:获取文件的属性
    参数:
    path:文件路径
    buf:保存文件的相关属性信息
struct stat {
     dev_t     st_dev;     /* ID of device containing file */
     ino_t     st_ino;     /* inode number */
     mode_t    st_mode;    /*文件类型、文件的权限 */
     nlink_t   st_nlink;   /* 硬链接数*/
     uid_t     st_uid;     /*用户id */
     gid_t     st_gid;     /* 组id */
     dev_t     st_rdev;    /* device ID (if special file) */
     off_t     st_size;    /*字节大小 */
     blksize_t st_blksize; /* blocksize for file system I/O */
     blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
     time_t    st_atime;   /* time of last access */
     time_t    st_mtime;   /*最后一次修改文件的时间*/
     time_t    st_ctime;   /* time of last status change */
 };
 

返回值:成功:0
失败:-1,更新errno

文件类型:将st_mode传到宏函数的判断是什么类型的文件

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.)

getpwuid
getgrgid

作业:
1.用文件io实现图片的复制。

/*************************************************************************
	> File Name: cpPhotosByIo.c
	> Created Time: Tue 17 Aug 2021 06:44:18 PM CST
	> Author: noah
 ************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{

	int fd;
	if ((fd = open("nier.png", O_RDONLY)) < 0) {
		perror("open.");
		exit(-1);
	}
	int fd2;
	if ((fd2 = open("nierNew.png", O_CREAT | O_WRONLY, 0666)) < 0) {
		perror("open fd2.");
		exit(-1);
	}
	char buf[32];
	size_t size;
	while(size = read(fd, buf, 32)) {
		write(fd2, buf, size);
	}
	return 0;

}

2.用标准io的直接iO实现结构体的写入和读出。

/*************************************************************************
	> File Name: fread_fwrite.c
	> Created Time: Tue 17 Aug 2021 11:24:37 AM CST
	> Author: noah
 ************************************************************************/
#include <stdio.h>
#include <stdlib.h>

typedef struct node {
	int a;
	int b;
}node_t;

int main(int argc, char *argv[])
{

	FILE *fp;
	if (!(fp = fopen("fread_write.txt", "w+"))) {
		perror("fopen.");
		exit(1);
	}
#if 0
	int st[5] = {1, 2, 3, 4, 5};
	fwrite(st, sizeof(int), 5, fp);
	rewind(fp); //go to base;
	int a[5];
	fread(a, sizeof(int), 5, fp);
	for (int i = 0; i < 5; i++) {
		printf("%d\n", a[i]);
	}
#endif
	node_t st[5];
	for (int i = 0; i < 5; i++) {
		st[i].a = i;
		st[i].b = i*3;
	}
	fwrite(st, sizeof(node_t), 5, fp);
	rewind(fp); //go to base;
	node_t a[5];
	fread(a, sizeof(node_t), 5, fp);
	for (int i = 0; i < 5; i++) {
		printf("%d\t%d\n", a[i].a, a[i].b);
	}
	fclose(fp);

	return 0;

}

3.实现:ls -l file

/*************************************************************************
	> File Name: ls-lByC.c
	> Created Time: Tue 17 Aug 2021 06:59:07 PM CST
	> Author: noah
 ************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <grp.h>
#include <pwd.h>
#include <time.h>

int main(int argc, char *argv[])
{

	DIR	*dirr = opendir(argv[1]);        //all members under dir
	struct dirent *dir = NULL;           //each member
	struct stat sta;                     //stat can get infomeation of each file
	struct passwd *pw;                   //user name
	struct group *gp;                    //group name
	struct tm *ti;                       //retime
	while(dir = readdir(dirr)) {
		stat(dir->d_name, &sta);         //get each file's information
#if 1
		switch (sta.st_mode & S_IFMT) {  //file type
			case S_IFBLK  : putchar('b'); break;
			case S_IFCHR  : putchar('c'); break;
			case S_IFDIR  : putchar('d'); break;
			case S_IFREG  : putchar('-'); break;
			case S_IFLNK  : putchar('l'); break;
			case S_IFSOCK : putchar('S'); break;
			case S_IFIFO  : putchar('p'); break;
			default : putchar('?'); break;
		}
#endif
		for (int i = 8; i >= 0; i--) {
			if(sta.st_mode & (1 << i)) {
				switch (i % 3) {        //power
					case 2 : putchar('r'); break;
					case 1 : putchar('w'); break;
					case 0 : putchar('x'); break;
				}
			}
			else putchar('-');
		}
		printf(" %2ld ", sta.st_nlink); //link numbers
		pw = getpwuid(sta.st_uid);      //user
		gp = getgrgid(sta.st_gid);      //group
		printf("%s %s ", pw->pw_name, gp->gr_name);
		printf("%7ld ", sta.st_size);   //file size
		ti = localtime(&sta.st_mtime);
		switch (ti->tm_mon + 1) {       //mon
			case 1  : printf(" Jan "); break;
			case 2  : printf(" Feb "); break;
			case 3  : printf(" Mar "); break;
			case 4  : printf(" Apr "); break;
			case 5  : printf(" May "); break;
			case 6  : printf(" Jun "); break;
			case 7  : printf(" Jul "); break;
			case 8  : printf(" Aug "); break;
			case 9  : printf("Sept "); break;
			case 10 : printf(" Oct "); break;
			case 11 : printf(" Nov "); break;
			case 12 : printf(" Dec "); break;

		}
		printf("%2d ", ti->tm_mday);
		if(ti->tm_year == 121) {
			printf("%2d:", ti->tm_hour);
			if (ti->tm_min < 10) {
				printf("0%d ", ti->tm_min);
			}
			else 
				printf("%2d ", ti->tm_min);
		}
		else printf("%5d ", 1900+ti->tm_year);
		printf("%s\n", dir->d_name);
	}
	return 0;

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值