三:文件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;
}
1862

被折叠的 条评论
为什么被折叠?



