目录
文件IO函数
open 打开 / close 关闭
write 写 / read 读
lseek
1. 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);
参数:
-
char *pathname: 指定要打开的文件路径以及名字;
-
int flags:打开方式
int flag 解释 O_RDONLY 只读 O_WRONLY 只写 O_RDWR 读写 ----以上三种,必须且只能包含一个---- O_APPEND 追加的方式 O_CREAT 如果文件不存在,则创建一个普通文件; O_TRUNC 如果文件存在,则清空文件; 如果需要多个选项,则可以用按位或(‘|’)连接
fopen() mode open() flags r O_RDONLY r+ O_RDWR w O_WRONLY w+ O_RDWR a O_WRONLY a+ O_RDWR -
mode_t mode:在文件创建时候,指定文件权限使用。
例如:
- 0664 :110 110 100 rw- -rw- -r–
- 0777 : 111 111 111 rwx-rwx-rwx
当flags中指定了 O_CREAT (创建)或者 O_TMPFILE(清空) 的时候,mode参数必须填写
当flags没有指定上述两种选项,则mode参数会被忽略
返回值:
- 成功,返回新的文件描述符;
- 失败,返回-1,更新errno;
int fd = open("./open.txt", O_WRONLY|O_CREAT|O_TRUNC, 0664);
if(fd < 0)
{
perror("open");
return -1;
}
printf("open success fd=%d\n", fd);
2.umask
所创建文件的模式为(mode & ~umask)
mode 0777 —> 111 111 111 & ~umask 111 111 101 —> umask 000 000 010 ===> 0002 111 111 111
2.1什么是umask
文件权限掩码,会影响文件创建时候的权限。从而保证某个用户没有指定的某种权限
2.2 umask获取
终端输入 umask
2.3 修改umask
- 终端输入 umask 0 umask 0022 只在设置终端有效
- 用umask函数设置
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
umask(0); 将umask设置为0
3.close
功能: 关闭文件,释放文件描述符对应的该空间
原型:
#include <unistd.h>
int close(int fd);
参数:
- int fd:指定要关闭的文件;
返回值:
- 成功返回0;
- 失败,返回-1,更新errno;
4. write
功能:将数据写入到文件中
原型:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
参数:
-
int fd:指定要写入到哪个文件中,填对应的文件描述符;
-
void *buf:指定要输出的数据首地址,可以输出任意类型数据;
-
size_t count:指定要输出的数据大小,以字节为单位;
返回值:
- 成功,返回成功输出的字节数;
- 失败,返回-1,更新errno.
5.read
功能:从指定的文件中读取数据;
原型:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
参数:
-
int fd:指定要读取哪个文件,填对应的文件描述符;
-
void *buf:存储读取到的数据;
-
size_t count:指定要读取多少个字节;
返回值:
- 0 成功,返回成功读取到的字节数;
- =0 读取到文件结尾;
- =-1 失败,返回-1,更新errno.
注意:
-
read不会自动补充\0字符
-
read函数遇到\n不会停止读取
练习:
用read和write拷贝一个图片,图片可以从widows拖入。
或者在ubuntu环境中按下prt sc按键截图,截图在~/Picture文件夹下。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fp = open("1.png", O_RDONLY);
int fp1 = open("2.png", O_WRONLY | O_CREAT | O_TRUNC, 0777); // 写,创建,清空,0777权限
if (fp < 0)
{
perror("1.png open:");
system("pause");
return -1;
}
if (fp1 < 0)
{
perror("2.png open:");
system("pause");
return -1;
}
char buf[10] = "";
while (1)
{
ssize_t re = read(fp, buf, sizeof(buf)); // read遇到\0\n都不结束
// printf("%s", buf);
write(fp1, buf, re); // 只写入读取到的字节个数
if (re == 0)
{
break;
}
}
close(fp);
close(fp1);
}
6. lseek
功能:修改文件偏移量;
原型:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
参数:
-
int fd:指定要修改哪个文件偏移量,填上对应的文件描述符;
-
off_t offset:偏移量,新的位置位whence加上offset参数,
-
若想往结尾偏移,则填正数
-
若想往开头偏移,则填负数;
-
-
int whence:
- SEEK_SET, 文件开头
- SEEK_CUR, 文件当前位置
- SEEK_END 文件结尾位置
返回值:
- 成功,返回文件偏移后的当前位置,距离文件开头的偏移量;
- 失败,返回(off_t)-1; 更新errno;
注:lseek(fd, 0, SEEK_END); 返回值为文件的大小;
练习:用read和write拷贝一个图片,
图片可以从widows拖入。或者在ubuntu环境中按下prt sc按键截图,截图在-/Picture文件夹下。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*
程序要求:
用read和write拷贝一个图片,
图片可以从widows拖入。或者在ubuntu环境中按下prt sc按键截图,截图在-/Picture文件夹下。
*/
int main()
{
int fp = open("1.png", O_RDONLY);
int fp1 = open("2.png", O_WRONLY | O_CREAT | O_TRUNC, 0777); // 写,创建,清空,0777权限
if (fp < 0)
{
perror("1.png open:");
system("pause");
return -1;
}
if (fp1 < 0)
{
perror("2.png open:");
system("pause");
return -1;
}
char buf[10] = "";
while (1)
{
ssize_t re = read(fp, buf, sizeof(buf)); // read遇到\0\n都不结束
// printf("%s", buf);
write(fp1, buf, re); // 只写入读取到的字节个数
if (re == 0)
{
break;
}
}
close(fp);
close(fp1);
}
文件属性相关函数
-rw-rw-r-- 1 ubuntu ubuntu 380 三月 24 17:24 01_fileno.c
代码段 | 解析 |
---|---|
-rw-rw-r– | 分别对应用户权限,用户组权限,其他用户权限 |
1 | 硬链接数 |
ubuntu | 文件所属用户名 |
ubuntu | 文件所属组用户名 |
380 | 文件大小(字节byte) |
三月 24 17:24 | 修改日期 |
01_fileno.c | 文件名 |
1. stat
**功能: ** 获取文件所有属性;
原型:
//头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);
参数:
- char *pathname:指定要获取哪个文件的属性,填上对应的文件路径以及文件名;
- struct stat statbuf:存储获取到的文件属性;
返回值:
- 成功,返回0;
- 失败,返回-1,更新errno;
struct stat
{
dev_t st_dev; // ID of device containing file
ino_t st_ino; // Inode number inode号
mode_t st_mode; // File type and mode 文件类型以及文件权限
nlink_t st_nlink; // Number of hard links 硬链接数
uid_t st_uid; // User ID of owner 文件所属用户的id号 uid
gid_t st_gid; // Group ID of owner 文件所属组用户的id号 gid
dev_t st_rdev; // Device ID (if special file)
off_t st_size; // Total size, in bytes 文件大小
blksize_t st_blksize; // Block size for filesystem I/O
blkcnt_t st_blocks; // Number of 512B blocks allocated
}
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
2. 提取文件权限
mode_t st_mode; /* File type and mode */ 文件类型以及文件权限
int a = 0400;//代表八进制数据
mode_t 本质上是一个整型数,且mode_t 是 unsigned int类型。
变量的后9bit存储了文件的权限。
mode: 0100664
0664---> 110 110 100
& 100 000 000 ---> 0400
---------------
100 000 000 --》 0400 不等于0,所以打印'r'
0664---> 110 110 100
& 010 000 000 ---> 0200
---------------
010 000 000 --》 0200 不等于0,所以打印'w'
0664---> 110 110 100
& 001 000 000 --->0100
---------------
000 000 000 --》 0 等于0,所以打印'-'
作业1:解析文件的权限,把秒数改为时间
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
void get_mode(mode_t m, char *str); // 问价类型解析函数
int main(int argc, const char *argv[])
{
struct stat buf;
if (stat("1.png", &buf) < 0)
{
perror("stat:");
system("pause");
return -1;
}
printf("mode: %o\n", buf.st_mode); // 文件类型及文件权限
char str[10] = "";
get_mode(buf.st_mode, str); // 文件类型权限解析函数
printf("%s\n", str);
printf("link: %ld\n", buf.st_nlink); // 硬链接数
printf("uid: %d\n", buf.st_uid); // 文件所属用户的id号
printf("gid: %d\n", buf.st_gid); // 文件所属组的id号
printf("size: %ld\n", buf.st_size); // 文件大小
printf("time: %ld\n", buf.st_ctime); // 文件修改时间
struct tm *tt = localtime(&buf.st_ctime);
printf("%d月 %d %d:%d", tt->tm_mon + 1, tt->tm_mday, tt->tm_hour, tt->tm_min);
system("pause");
return 0;
}
/*文件类型权限解析函数*/
void get_mode(mode_t m, char *str)
{
// printf("%s\n",str);
int t = 0400;
char per[3] = "rwx";
// printf("%o\n", m);
for (int i = 0; i < 9; i++, t >>= 1)
{
if ((m & t) == 0)
{
*(str + i) = '-';
// putchar('-');
continue;
}
*(str + i) = per[i % 3];
// putchar(per[i % 3]);
}
// printf("\n");
// printf("%s\n", str);
}