1.文件IO
<br />#include <stdio.h><br />#include <stdlib.h><br />#include <string.h><br />#include <sys/types.h><br />#include <sys/stat.h><br />#include <unistd.h><br />#include <errno.h><br />#include <sys/wait.h><br />
```
vi /usr/include/unistd.h
/ Standard file descriptors. /
#define STDIN_FILENO 0 / Standard input. /
#define STDOUT_FILENO 1 / Standard output. /
#define STDERR_FILENO 2 / Standard error output. /
```
open
描述: 打开或者新建一个文件
原型:
#include
#include
#include
int open(const char pathname, int flags);
int open(const char pathname, int flags, mode_t mode);
返回值:
成功,返回最小且未被占用的文件描述符
失败,返回-1,设置errno值
参数:
pathname既可以绝对路径也可以是相对路径.
flags
O_RDONLY
O_WRONLY
O_RDWR
O_APPEND
O_CREAT 若文件不存在则创建
需要结合mode. 文件最终权限 mode & ~umask
…
man 2 open
其中关于flags之O_NONBLOCK的说明
close
描述: 关闭文件
原型:
#include
int close(int fd);
返回值:
成功返回0
失败返回-1,并设置errno值
参数:
文件描述符
man 2 close
进程终止时,内核对进程尚未关闭的文件描述符调用close关闭它.
read
描述: 从打开的设备或文件中读取数据
原型:
#include
ssize_t read(int fd, void *buf, size_t count);
返回值:
>0,读取到的字节数
=0,读取到文件末尾(针对普通文件)
=0,远程关闭(针对网络编程)
-1,出错,并设置errno
参数:
fd:文件描述符
bu:读取的数据保存在缓冲区buf中
count:buf缓冲区可存放的最大字节数
man 2 read man 3 fread
对于Java程序而言 =-1,读取到文件末尾(针对普通文件) 源码位置:jdk-jdk8-b116\jdk\src\share\native\java\io\io_util.c
write
描述: 向打开的设备或文件中写入数据
原型:
#include
ssize_t write(int fd, const void *buf, size_t count);
返回值:
成功,返回写入的字节数. 且仅表示数据写入到内核缓冲区.
失败,返回-1,并设置errno(针对普通文件)
失败,返回-1,并设置errno=EPIPE(针对网络编程)
参数:
fd:文件描述符
buf:待写入的数据
count:buf中实际数据的大小
man 2 write
lseek
描述: 移动文件指针
原型:
#include
#include
off_t lseek(int fd, off_t offset, int whence);
返回值:
成功,则返回新的偏移量
参数:
fd:文件描述符
offset:含义取决于参数whence
若whence是SEEK_SET,文件偏移量将设置到offset字节位置.
若whence是SEEK_CUR,文件偏移量将设置到(current’location + offset)字节位置
若whence是SEEK_END,文件偏移量将设置到(file’size + offset)字节位置.
offset 可以正负
lseek常用操作
1.文件指针移动到头部
lseek(fd, 0, SEEK_SET)
2.获取文件指针当前位置
int len = lseek(fd, 0, SEEK_CUR)
3.获取文件长度
int len = lseek(fd, 0, SEEK_END)
4.实现文件随机读写
off_t currpos = lseek(fd, 1000, SEEK_END); // 从文件尾部向后拓展1000个字节
write(fd, “v”, 1); // 额外执行一次写操作(数据任意), 否则文件无法完成拓展
产生空洞文件 [ 代码 ]
1.使用od命令可以查看空洞文件中的空洞
od -c tmp.txt
2.一个文件的大小不等于文件在磁盘所占用的空间
2.1若无空洞或空洞比较少,则文件大小<=所占磁盘空间 [ 图 ]
2.2若空洞比较大,则文件大小>所占磁盘空间
2.3空洞是否占用磁盘空间是由文件系统决定
3.查看文件所占磁盘空间
du -h tmp.txt
perror
描述:
原型:
#include
#include
#include
void perror(const char *s);
常见操作
1.perror(“Fail”);
2.fprintf(stderr, “Fail: %s\n”, strerror(errno));
查阅常见错误码 man 3 errno
2.标准IO
文件描述符与文件指针相互转换
描述: 将文件指针转换为文件描述符
原型:
#include
int fileno(FILE *stream);
描述: 将文件描述符转换为文件指针
原型:
#include
FILE fdopen(int fd, const char mode);
3.文件与目录
3.1文件操作相关
stat/lstat
描述: 获取文件属性
原型:
#include
#include
#include
int stat(const char pathname, struct stat statbuf);
int lstat(const char pathname, struct stat statbuf);
返回值:
成功返回0
失败返回-1
```
struct stat {
dev_t st_dev; / ID of device containing file /
ino_t st_ino; / Inode number /
mode_t st_mode; / File type and mode / 文件类型和权限
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; / Block size 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 */<br /> struct timespec st_mtim; /* Time of last modification */<br /> struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */<br /> #define st_mtime st_mtim.tv_sec<br /> #define st_ctime st_ctim.tv_sec<br />};<br />```
man 2 stat man 7 inode
使用stat判断文件类型 [ 代码 ]
使用stat判断文件权限 [ 代码 ]
3.2目录操作相关
opendir
描述: 打开一个目录
原型:
#include
#include
DIR opendir(const char name);
返回值:
指向目录的指针
参数:
绝对或相对路径
man 3 opendir
readdir
描述: 读取目录内容-目录项
原型:
#include
struct dirent readdir(DIR dirp);
返回值:
读取的目录项指针
参数:
指向目录的指针(即opendir函数的返回值)
目录中每个文件称为目录项
<br />struct dirent {<br /> ino_t d_ino; /* Inode number */<br /> off_t d_off; /* Not an offset; see below */<br /> unsigned short d_reclen; /* Length of this record */<br /> unsigned char d_type; /* Type of file; not supported<br /> by all filesystem types */ 文件类型<br /> char d_name[256]; /* Null-terminated filename */ 文件名<br />};<br />
文件类型如下
块设备:应用程序可以随机访问设备数据.数据的读写必须以块的(通常512B)倍数进行操作,不支持基于字符的操作.
字符设备:提供连续的数据流,应用程序可以顺序读取,通常不支持随机存取.数据的读写按字节/字符进行操作.
closedir
描述: 关闭目录
原型:
#include
#include
int closedir(DIR *dirp);
返回值:
成功返回0
失败返回-1
读取目录内容一般步骤
1.DIR pDir = opendir(const char name);
2.while ( (p = readdir(pDir)) != NULL ) {}
3.closedir(pDir);
特别注意: 递归遍历指定目录下的所有文件的时候, 要过滤掉 . 和 .. 文件, 否则进入无限循环.
3.3 dup
描述: 复制文件描述符,让复制出的新文件描述符指向与oldfd同一个文件.
原型:
#include
int dup(int oldfd);
返回值:
成功,返回最小且未被占用的文件描述符
失败,返回-1,设置errno值
参数:
oldfd表示要复制的文件描述符
newfd和oldfd指向同一个文件
man 2 dup
3.4 dup2
描述: 复制文件描述符,让newfd指向与oldfd同一个文件.
原型:
#include
int dup2(int oldfd, int newfd);
返回值:
成功返回0. 表示两个文件描述符指向同一个文件
失败返回-1,设置errno值
参数:
oldfd表示原文件描述符
newfd表示新文件描述符
如果newfd已经指向一个文件,则首先关闭已指向的文件,再指向oldfd表示的文件.
man 2 dup2
3.5 fcntl
描述: 改变已打开文件的属性
原型:
#include
#include
int fcntl(int fd, int cmd, … / arg / );
若cmd是F_DUPFD, 复制文件描述符, 与dup相同 若cmd是F_GETFL, 获取文件描述符的flags属性值 若cmd是F_SETFL, 设置文件描述符的flags属性
返回值: 取决于cmd
成功
若cmd是F_DUPFD, 返回一个新的文件描述符
若cmd是F_GETFL, 返回文件描述符的flags属性值
若cmd是F_SETFL, 返回0
失败返回-1,设置errno值
man 2 fcntl
fcntl常用操作
1.复制一个新的文件描述符
int newfd = fcntl(fd, F_DUPFD, 0);
2.获取文件的属性标志
int flag = fcntl(fd, F_GETFL, 0);
3.设置文件属性标志
flag = flag | O_APPEND;
fcntl(fd, F_SETFL, flag);
4.常用属性标志
O_APPEND
O_NONBLOCK - 设置打开的文件描述符为非阻塞
4.其他
4.1宏的使用
```
#define ERR_EXIT(m) (perror(m), exit(EXIT_FAILURE))
vi /usr/include/stdlib.h
#define EXIT_FAILURE 1 / Failing exit status. /
#define EXIT_SUCCESS 0 / Successful exit status. /
```
<br />#define ERR_EXIT(m) \<br /> do \<br /> { \<br /> perror(m); \<br /> exit(EXIT_FAILURE); \<br /> } while (0)<br />
4.2进程和系统打开文件最大数
进程打开文件最大数
ulimit -a ulimit -n
系统打开文件最大数
cat /proc/sys/fs/file-max