文件IO 01 day28

三:文件IO

一:定义

操作系统为了方便用户使用系统功能而对外提供的一组系统函数。称之为 系统调用 其中有个 文件IO
一般都是对设备文件操作,当然也可以对普通文件进行操作。

一个基于Linux内核的没有缓存的IO机制

特性:
.1 没有缓存区
.2 操作对象不在是流,而是文件描述符 FILE* 4
.3文件描述符
很小的非负的整数 int 0-1023操作系统最多开1k
内核每打开一个文件就会获得一个文件 描述符

​ 每个程序在启动的时候操作系统默认为其打开
​ 三个描述符与流对象匹配:

	  0 ==>STDIN_FILENO === stdin//终端上的键盘输入
	  1 ==>STDOUT_FILENO == stdout//终端上输出
	  2 ==>STDERR_FILENO == stderr//报错
	  stdin,stdout,stderr,===>FIL

二:linux下的文件类型

b block //块设备文件 eg:硬盘
c character //字符设备文件 ég:鼠标,键盘
d directory //目录文件 eg::文件夹
regular //常规文件 eg:1.txt 0l.sh1 xx.bmp
l Symblink //软链接 eg:快捷方式
s socket //套接字 eg:网络通信用
p pipe //管道 eg:进程间通信

linux操作文件的函数

​ 两套函数(两套操作路径):

​ (1)系统调用— 内核提供的函数

​ (2)库函数第三方提供的函数

三:基础函数

一:权限(标志位)

O_RDONLY //只读

O_WRONLY //只写

O_RDWR //读写

O_APPEND //追加

O_CREAT //文件不存在,创建

O_TRUNC //文件存在 截短为0

READ	WRITE	Execute
- 			rw-   		rw-   	r--
				110         100
				6     		6    	4
文件的类型	作者的权限	组用户的权限	其他人
二:open

记得要0666而不是666,前面是八进制,后面是十进制

int open(const char *pathname, int flags);//flags标志位
int open(const char *pathname, int flags, mode_t mode);//mode_t mode权限
//需要新建文件,需要权限

@pathname //打开的文件

返回值: 成功 :文件描述符(fd

	      失败 : -1 && `errno`会被设置
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

int	main(int argc, char **argv)
{
    int fd = open("1.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
    if(-1 == fd)
    {
        printf("open error\n");
        return -1;
    }


    //system("pause");
    return 0;
}

如果权限是0777:实际创建文件不是0777,而是0775

因为umask = 0002(掩码) //二进制 —遮住

最终文件的权限 = ~umask & mode,一般给mode权限一般是0666

三:write/read
ssize_t write(int fd, const void *buf, size_t count);//检查错误检查fd

char buf[1024];
功能: 通过文件描述符向文件中写一串数据
参数: fd:文件描述符
buf:要写入文件的字符串的首地址
count:要写入字符的个数
返回值:(用int/ssize_t都行)
成功返回实际写入的个数 //要是0,不是错误(和设备有关系)
失败返回-1

int fd = open("1.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
  if (-1 == fd)
  {
    printf("open error\n");
    return 1;
  }

  char buf[128]="hello";
  ssize_t ret = write(fd,buf,strlen(buf)); // 第三个参数 有效数据的长度
  // ret>0   实际写入的字节数  ==0 一个字符也没有写入(不是错误,和设备有关) -1 错误
  // system("pause");
  printf("ret :%ld\n",ret);
  close(fd);
ssize_t read(int fd, void *buf, size_t count);

功能: 通过文件描述符读取文件中的数据
参数: fd:文件描述符
buf:存放数据空间的首地址
count:要读到数据的个数
返回值: 成功返回读到数据的个数
失败返回-1
读到文件结尾返回0

int fd = open("1.txt", O_RDONLY);
  if (-1 == fd)
  {
    printf("open error\n");
    return 1;
  }

  while (1)
  {
    char buf[1024] = {0};
    int ret = read(
        fd, buf,
        sizeof(buf));  // 第三参数 可以比实际内容大 ,返回值代表实际读到的字节数
    // ret  >0 实际读到字节数 ==0 end of file -1  错误
    if (0 == ret)
    {
      break;
    }
    printf("%s\n", buf);
  }

  close(fd);
四:cp
int main(int argc, char **argv) {
  if (argc != 3) {
    printf("Usage: %s<filename>\n", argv[0]);
    return -1;
  }
  int fd1 = open(argv[1], O_RDONLY);
  int fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
  if (-1 == fd2 || -1 == fd2) {
    printf("open error2\n");
    return 1;
  }

  while (1) {
    char buf[1024] = {0};
    int ret = read(fd1, buf, sizeof(buf));
    if (0 == ret) {
      break;
    }
    write(fd2, buf, ret);//如果ret写成sizeof,会导致读到的字节比实际读取大sizeof整数倍,可能与实际不符合
  }
  close(fd1);
  close(fd2);
五:lseek
off_t lseek(int fd, off_t offset, int whence);

功能: 定位光标的位置
参数: fd:文件描述符
offset:偏移量
正:向后偏移,负:向前偏移,零:不偏移

whence:
​ SEEK_SET
​ SEEK_CUR
​ SEEK_END

返回值: 成功返回偏移量
失败返回-1

//和fseek类似,但有缺陷  
int fd = open("1.txt",O_RDWR);
    if(-1 == fd)
    {
        printf("open error\n");
        return -1;
    }

    int ret = lseek(fd, 10, SEEK_SET);
    if(-1 == ret)
    {
        printf("lssek error\n");
        return 1;
    }

    printf("offset %d\n",ret);
    write(fd, "stdio", 5);
    close(fd);

1、不支持O_APPEND的追加模式,无法生成空洞文件。
2、lseek函数执行失败,文件指针还在偏移前的位置。
3、lseek函数在设备文件上偏移无效。

六:fileno
FILE* fp -> int fd
int fileno(FILE *stream);

功能: 获得一个文件流指针中的文件描述符
参数: stream:文件流指针
返回值: 成功返回文件描述符
失败返回-1

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

int	main(int argc, char **argv)
{
    FILE* fp = fopen("1.txt","r");
    if(NULL == fp)
    {
        return 1;
    }

    int fd = fileno(fp);
    if(-1 == fd)
    {
        return 1;
    }  

    char buf[256];
    read(fd, buf, sizeof(buf) - 1);
    printf("%s\n",buf);

    fclose(fp);
    
    //system("pause");
    return 0;
}
七:fdopen
int fd -> FILE *fp
FILE *fdopen(int fd, const char *mode);

功能: 将文件描述符转化为文件流指针
参数: fd:已经打开的文件描述符
mode:“r”,“r+”,“w”,“w+”,“a”,“a+”
返回值: 成功返回文件流指针
失败返回NULL

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

int	main(int argc, char **argv)
{
    int fd = open("1.txt",O_RDONLY);
    if(-1 == fd)
    {
        return 1;
    }

    FILE* fp = fdopen(fd, "r");
    if(NULL == fp)
    {
        return 1;
    } 

    char buf[256] = {0};
    fgets(buf, sizeof(buf), fp);
    printf("%s\n",buf);
    fclose(fp);

    //system("pause");
    return 0;
}

四:目录

 man readdir	//查看结构体和类型
DT_BLK      This is a block device.
DT_CHR      This is a character device.
DT_DIR      This is a directory.
DT_FIFO     This is a named pipe (FIFO).
DT_LNK      This is a symbolic link.
DT_REG      This is a regular file.
DT_SOCK     This is a UNIX domain socket.
DT_UNKNOWN  The file type could not be determined.

一:opendir/readdir

#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);//文件名
struct dirent *readdir(DIR *dirp);//上面的DIR*的目录流指针
struct dirent {
	ino_t          d_ino;       /* Inode number */
    off_t          d_off;       /* Not an offset; see below */
    unsigned short d_reclen;    /* Length of this record */
	unsigned char  d_type;      /* Type of file; not supported by all filesystem types */	//文件的类型
	char           d_name[256]; /* Null-terminated filename */ 	//以空结尾的文件名
           };
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv) {
  DIR *dir = opendir("./");
  if (NULL == dir) {
    printf("opendir error\n");
    return 1;
  }

  while (1) {
    struct dirent *info = readdir(dir);
    if (NULL == info) {
      break;
    }
    switch (info->d_type) {
    case DT_REG:
      printf("普通文件\t");
      break;
    case DT_DIR:
      printf("目录文件\t");
      break;
    default:
      printf("其他文件\t");
      break;
    }
    printf("%s\n", info->d_name);
  }

  closedir(dir);

  // system("pause");
  return 0;
}

二:chidir/getcwd

int chdir(const char *path);

功能: 改变当前程序的工作路径
参数: path:改变到的路径
返回值: 成功返回0
失败返回-1

char *getcwd(char *buf, size_t size);

功能: 获得当前的工作路径
参数: buf:保存工作路径空间的首地址
size:保存路径空间的长度
返回值: 成功返回包含路径空间的字符串首地址
失败返回NULL

#include <stdio.h>
#include <unistd.h>

int	main(int argc, char **argv)
{
    char curpath[512] = {0};//一般大于等于256
    getcwd(curpath, sizeof(curpath));
    printf("cur : %s\n",curpath);
    chdir("../");
    fopen("3.txt", "w");
    getcwd(curpath, sizeof(curpath));
    printf("cur : %s\n",curpath);

    //system("pause");
    return 0;
}

三:mkdir/rmdir

int mkdir(const char *pathname, mode_t mode)//此时一般给0777

功能: 创建一个目录
参数: pathname:路径
mode: mode & ~umask 0002

返回值: 成功返回0
失败返回-1

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

int	main(int argc, char **argv)
{
    int ret = mkdir("123", 0777);
    if(-1 == ret)
    {
        printf("mkdir error\n");
        return 1;
    }

    //system("pause");
    return 0;
}

int rmdir(const char *pathname)

功能: 删除一个空目录文件
参数: pathname:目录文件的名字
返回值: 成功返回0
失败返回-1

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int	main(int argc, char **argv)
{
    int ret = rmdir("123");
    if(-1 == ret)
    {
        printf("rmdir error\n");
        return 1;
    }

    //system("pause");
    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值