您的位置:首页 > 其它

目录-文件

2016-04-02 14:42 267 查看
文件IO(unix)

everything is a file in unix.

文件描述符(file descriptor), 操作文件必须通过文件描述符。(进程文件表项的下标)

>=0的整数

在unix下,操作系统会为每个进程自动打开三个设备:

标准输入设备:STDIN_FILENO

标准输出设备:STDOUT_FILENO

标准出错设备:STDERR_FILENO

//printf("hello");

//=> write(STDOUT_FILENO, "hello", 5);

文件IO操作接口函数(API) (fileIO.c)

1.打开/关闭一个文件

2.读写一个文件

//3. ioctl

3. 定位

4. mmap/munmap

1. 打开/关闭一个文件

NAME

open, creat - open and possibly create a file or device

SYNOPSIS

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

open用来打开一个文件(或创建一个文件并打开它)

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

pathname: 要打开的文件的文件名(带路径)

flags: 打开标志。用位域实现

O_RDONLY: RD, read 只读打开

O_WRONLY: WR, write只写打开

O_RDWR: read write 读写打开

以上三个标志任选其一

O_APPEND: 追加方式。

O_CREAT : create创建标志(如果文件不存在则创建)

O_NONBLOCK: non block 非阻塞方式打开。

"阻塞方式": 如果文件为空,read则会等待

"非阻塞方式":你懂的

O_EXCL: 该标志一般和O_CREAT 配合使用(O_CREAT | O_EXCL),

用来测试文件是否存在。指定O_CREAT | O_EXCL,

如果文件存在,则open会失败,并且errno == EEXIST

O_TRUNC: truncate(剪断), 截短标志.(清零)

假如文件存在,并且是一个普通文件,而且

打开方式是O_RDWR或 O_WRONLY,则文件内容会被

清空。

...

mode: 用来指定新创建的文件的权限,有两种方式:

(1) S_IRUSR, S_IWUSR, S_IXUSR -> S_IRWXU == S_IRUSR | S_IWUSR | S_IXUSR

S_IRGRP, S_IWGRP,S_IXGRP -> S_IRWXG ==

S_IROTH, S_IWOTH, S_IXOTH -> S_IRWXO ==

S_IRUSR | S_IRGRP | S_IROTH

(2) 0660

返回值:

如果成功返回一个文件描述符,后续对该文件的操作

都必须通过此文件描述符。

失败返回-1, errno被设置

creat仅用来创建一个文件,

int creat(const char *pathname, mode_t mode);

成功返回0,失败返回-1

=====

NAME

close - close a file descriptor

SYNOPSIS

#include <unistd.h>

int close(int fd);

2. 读写一个文件 read/write

NAME

read - read from a file descriptor

SYNOPSIS

#include <unistd.h>

read用来从fd指定的文件中,读取 count个字节到

buf指定的内存空间。

ssize_t read(int fd, void *buf, size_t count);

fd: 文件描述符,表示要从哪个文件里读数据

buf: 指针,指向一段内存,用来保存从文件中读取

到的数据

count: 表示要读多少字节数据

返回值:

> 0 表示成功读取到的数据的字节数

= -1: 表示失败了,errno被设置

=0: 表示文件结束了。

==

NAME

write - write to a file descriptor

SYNOPSIS

#include <unistd.h>

write用来把buf指向的内存空间中的前面count个字节

写到fd指定的文件中去

ssize_t write(int fd, const void *buf, size_t count);

fd: 文件描述符,表示要写到哪个文件中去

buf:指针,指向要写的数据

count:表示要写多少字节数据

返回值:

> 0: 表示成功写了多少个字节

=-1: 失败了,errno被设置

=0: 表示什么也没写。

练习:

用文件IO的接口写一个程序,来实现两个文件的拷贝。

read/write成功后,光标位置会自动增加n个位置(n表示你成功读或写的

字节数)

3.定位光标

NAME

lseek - reposition read/write file offset

SYNOPSIS

#include <sys/types.h>

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

fd: 要重定位的文件

offset: 偏移量,可正可负,具体含义需要结合第三个参数

whence: 定位方式,有三种:

SEEK_SET: 基于文件开头定位

SEEK_CUR: 基于文件当前位置定位

SEEK_END: 基于文件末尾定位

返回值:

成功返回新光标位置相对于文件开头的偏移量(以字节为单位)

失败返回-1, errno被设置。

例子:

如何求一个文件的大小?

unsinged long filesize = lseek(fd, 0, SEEK_END);

注意:

我们在实际读写文件前,一般要先定位lseek

我们能不能像操作内存一样,去操作文件呢?

当然可以。

需要用到mmap

4. mmap

NAME

mmap, munmap - map or unmap files or devices into memory

SYNOPSIS

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

addr: 映射地址,表示要映射到进程地址空间的哪个位置。

一般为NULL, 让操作系统自动为我选择一个合适的地址。

length:要映射的文件区域的长度。向上取PAGE_SIZE(4K)的整数倍

prot: 映射后内存区域的权限(应与文件打开权限一致,

因为操作此区域内存实际上就是操作文件内容)

PROT_EXEC:可执行

PROT_READ:可读

PROT_WRITE:可写可读

PROT_NONE:没访问权限

flags: 映射标志。决定对映射部分的操作是否对其他进程可见

MAP_SHARED: 共享。对其他进程可见,内存操作应用到文件中去

MAP_PRIVATE: 私有。对其他进程不可见,内存操作不应用到文件中去

fd: 文件描述符,表示要映射哪个文件

offset:偏移量,表示从文件哪个地方开始映射。

offset必须为PAGE_SIZE(4K)的整数倍

返回值:

成功返回映射后的内存首地址。

失败返回MAP_FAILED, errno被设置。

munmap就是解映射

int munmap(void *addr, size_t length);

addr: 要解映射的 首地址。PAGE_SIZE的整数倍。

length: 要解映射的长度。PAGE_SIZE

返回值:

成功返回0,

失败返回-1, errno被设置。

NOTE:

进程退出,会自动unmap,但是关闭文件不会自动unmap.

文件属性操作函数:

1.stat/fstat/lstat: get file status

2.access: 测试调用进程是否有权限去访问某个文件

3.umask : 设置文件权限掩码

4. chmod/fchmod 用来改变某个文件的权限位

5. chown/fchown/lchown 用来改变某个文件的所有者

6. truncate/ftruncate用来把某个文件截短

7. chdir 改变当前工作目录

getcwd获取当前目录的绝对路径

8. remove /unlink/rmdir 删除一个文件或目录

1. stat/fstat/lstat用来获取文件的属性信息

NAME

stat, fstat, lstat - get file status

SYNOPSIS

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

在linux内核中一个文件的属性(状态)信息,是用一个

结构体struct stat来描述的。如下:

struct stat {

//dev_t 在内核是用来表示设备号的。设备号相当于

//是设备的身份ID

dev_t st_dev; //设备号,容纳该文件的那个设备的设备号

ino_t st_ino; // inode number , i-node号

mode_t st_mode; //文件权限位

nlink_t st_nlink; //该文件的硬链接 数,

//硬链接与软链接的区别,你们要懂的。

uid_t st_uid; //文件所有者的ID(用户ID)

gid_t st_gid; //文件所有者的组ID

dev_t st_rdev; //文件的设备号(假如该文件是设备)

off_t st_size; // 文件内容的大小,以字节为单位

//普通文件,目录文件,符号链接文件

//上述三种文件的文件内容是什么?

//目录文件的内容:目录项数组

//符号链接文件的内容是: 保存它指向的文件的文件名

blksize_t st_blksize;//文件系统的块大小

blkcnt_t st_blocks; //占多少块(固定以512为块大小)

time_t st_atime; // 最后访问时间,"文件内容"

time_t st_mtime; //最后修改时间,"文件内容"

time_t st_ctime; //最后改变时间,"文件属性", i-node

};

stat用来把path指定的文件的属性信息,保存到

buf指向的结构体struct stat 中。

int stat(const char *path, struct stat *buf);

fstat功能与返回值与stat 一样,只不过,fstat是用文件描述符

来指定文件的。

int fstat(int fd, struct stat *buf);

lstat功能与stat相同,只不过当path是一个符号链接时,获取的是符号

链接本身的属性信息,而不是它指向的文件。

int lstat(const char *path, struct stat *buf);

返回值:

成功返回0,

失败返回-1, errno被设置

例子:

struct stat st;

stat(path, &st);

st.st_size ->

st.st_mode 包含文件的类型与权限,用下列宏来解析:

S_ISREG(st.st_mode) 普通文件 regular file

S_ISDIR(st.st_mode) 目录文件directory

S_ISCHR(st.st_mode) 字符设备 char

S_ISBLK(st.st_mode) 块设备 block

S_ISFIFO(st.st_mode) 管道文件 pipe(无名管道,有名管道 fifo)

S_ISLNK(st.st_mode) 符号链接文件 link

S_ISSOCK(st.st_mode) 套接字文件 socket

权限位:

S_IRUSR , S_IRGRP, S_IROTH

S_IWUSR

S_IXUSR

if (st.st_mode & S_IRUSR)

{

//用户有读的权限

}

练习:

写一个程序,求任意一个文件的类型、权限、

以及文件(假如该文件是普通文件、目录文件、符号

链接文件)的大小.

文件的类型和权限请按命令ls -l的形式打印

2. access 用来测试调用进程是否有相应的权限去访问由pathname指定的文件

NAME

access - determine accessibility of a file

SYNOPSIS

#include <unistd.h>

int access(const char *pathname, int amode);

pathname: 要测试的文件

amode:要测试的访问权限, "按位或",可以测试多项权限

R_OK : 测试是否可读

W_OK : 测试是否可写

X_OK :测试是否可执行

F_OK :测试文件是否存在

R_OK | W_OK

返回值:

成功返回0, 所有测试权限都OK

失败返回-1, 至少有一项测试没通过

3 .umask 设置文件创建的掩码

NAME

umask - set and get the file mode creation mask

SYNOPSIS

#include <sys/stat.h>

掩码,当中为1的bit位, 表示你在创建文件时不能指定

mode_t umask(mode_t cmask);

umask(022);

open(,,0660);

=> 0644

4. chmod/fchmod:用来改变文件的权限

NAME

chmod, fchmod - change permissions of a file

SYNOPSIS

#include <sys/stat.h>

int chmod(const char *path, mode_t mode);

int fchmod(int fd, mode_t mode);

chmod第一个是文件名

fchmod第一个参数是文件描述符

mode:新的权限 ,有两种方式指定,你懂的。

(1) S_IRUSR

(2) 0660

返回值:

成功返回0,

失败返回-1, errno被设置

5. chown/fchown

NAME

chown, fchown, lchown - change ownership of a file

SYNOPSIS

#include <unistd.h>

int chown(const char *path, uid_t owner, gid_t group);

int fchown(int fd, uid_t owner, gid_t group);

6 .文件截短

NAME

truncate, ftruncate - truncate a file to a specified length

SYNOPSIS

#include <unistd.h>

#include <sys/types.h>

int truncate(const char *path, off_t length);

int ftruncate(int fd, off_t length);

NOTE:

假如原文件长度> length, 保留文件前面length长度,后面的没了

假如原文件长度< length, 文件长度延伸至length,

7. chdir改变当前工作目录

NAME

chdir, fchdir - change working directory

SYNOPSIS

#include <unistd.h>

int chdir(const char *path);

8. 获取进程当前工作目录的绝对路径名

NAME

getcwd, getwd, get_current_dir_name - get current working

directory

SYNOPSIS

#include <unistd.h>

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

char *get_current_dir_name(void);

9. 删除一个文件(普通文件或目录文件): remove

删除普通文件:

unlink

删除一个空目录:

rmdir

NAME

remove - remove a file or directory

SYNOPSIS

#include <stdio.h>

remove用来删除pathname指定的文件或目录

int remove(const char *pathname);

返回值:

成功返回0,

失败返回-1, errno被设置。

NAME

unlink - delete a name and possibly the file it refers to

SYNOPSIS

#include <unistd.h>

unlink用来删除一个文件系统中的名字或普通文件

int unlink(const char *pathname);

NAME

rmdir - delete a directory

SYNOPSIS

#include <unistd.h>

rmdir用来删除一个空目录

int rmdir(const char *pathname);

DESCRIPTION

rmdir() deletes a directory, which must be empty.

目录结构及目录操作:(dir.c)

1. 创建、删除目录

mkdir

rmdir

2. 打开一个目录

opendir

3. 读一个目录

readdir

4.关闭一个目录

closedir

目录作业:

1.写一个程序,删除一个目录(可能为空,也可能不为空)

2.写一个程序,求一个目录下面所有的图片文件(.bmp, .jpg)的个数

1. 创建、删除一个目录

NAME

mkdir - create a directory

SYNOPSIS

#include <sys/stat.h>

#include <sys/types.h>

mkdir用来创建一个目录

int mkdir(const char *pathname, mode_t mode);

pathname:要创建的目录的路径名

mode: 新创建的目录的权限,有两种方式指定:

(1) S_IRUSR, ...

(2) 0660

返回值:

成功返回0,

失败返回-1, errno被设置。

NAME

rmdir - 删除一个空目录

SYNOPSIS

#include <unistd.h>

int rmdir(const char *pathname);

2. 打开一个目录opendir

NAME

opendir, open a directory

SYNOPSIS

#include <sys/types.h>

#include <dirent.h>

在linux中,用结构体 DIR 来表示一个打开的目录。

DIR *opendir(const char *name);

name: 要打开的目录名

返回值:

如果成功,返回一个DIR的指针

如果失败,返回NULL, errno被设置。

3. 读一个目录readdir

一个目录的内容,目录项的数组。

那么目录项是个什么东西呢?

在linux下目录项用结构体struct dirent,定义如下:

struct dirent {

ino_t d_ino; //I-NODE编号

off_t d_off; //数组的下标

unsigned short d_reclen; //该结构体的长度

unsigned char d_type; //该目录项代表的文件的类型(不是所有文件系统都支持)

char d_name[256]; //该目录项代表的文件的文件名(不带路径)

};

d_ino, d_name只有这两个成员变量是被所有系统支持的。

NAME

readdir, - read a directory

SYNOPSIS

#include <dirent.h>

readdir用来从dirp指定的目录中,读取下一个

目录项(struct dirent)的指针。如果一个目录中有多个

目录项,那么你就需要调用readdir多次,直到它

返回NULL为止。

struct dirent *readdir(DIR *dirp);

返回值:

成功返回目录中下一个目录项的指针

如果失败或读完了,返回NULL。

如果errno设置了,就是表示失败了。

4. 关闭一个目录

NAME

closedir - close a directory

SYNOPSIS

#include <sys/types.h>

#include <dirent.h>

int closedir(DIR *dirp);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: