3. 文件与I/O
3. 文件与I/OO
read系统调用
函数原型
- 一旦有了与一个打开文件描述相连的文件描述符,只要该文件是用O_RDONLY或O_RDWR标志打并的,就可以用read()系统调用从该文件中读取字节
- 函数原型:
- ssize_t read(int fd, void buf, size_t count);
- 参数
- fd:想要读的文件的文件描述符
- buf :指向内存块的指针,从文件中读取来的字节放到这个内存块中
- count :从该文件复制到buf中的字节个数
- 返回值
- 如果出现错误,返回-1 , 读文件结束,返回0,否则返回从该文件复制到规定的缓冲f区中的字节数d
wirte系统调用
write
- 用write()系统调用将数据写到一个文件中
- 函数原型:
- ssize_t write(int fd,const void*buf, size_t count);
- ssize_t 为有符号数
- 函数参数:
- fd:要写入的文件的文件描述符
- buf:指向内存块的指针,从这个内存块中读取数据写入到文件中
- count:要写入文件的字节个数
- 返回值
- 如果出现错误,返回-1,如果写入成功,则返回写入到文件中的字节个数
读操作一般意味着数据已经从外存读到缓冲区了,但写操作不一定意味着从缓冲区写到外存,除非指定了同步选项(open函数指定 O_SYNC 的标志 或者通过函数fsync()进行同步)
例子
1 /* ************************************************************************
2 > File Name: 01cp.c
3 > Author: sansuitaibai
4 > email: 2657302908@qq.com
5 > Created Time: 2022年09月18日 17时31分29秒 CST
6 > Description:
7 ************************************************************************/
8 #include<sys/types.h>
9 #include<fcntl.h>
10 #include<sys/stat.h>
11
12 #include<stdio.h>
13 #include<string.h>
14 #include<stdlib.h>
15 #include<errno.h>
16 #include<unistd.h>
17
18 #define ERR_EXIT(m) \
19 do{ \
34 if(infd < 0){
35 ERR_EXIT("infd oped faul: ");
36 }
37 outfd = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC , 0644);
38 if(outfd <0){
39 ERR_EXIT("outfd open faul");
40 }
41 char buf[1024];
42 int nread = 0;
43 while((nread = read(infd,buf,1024)) > 0){
44
45 write(outfd,buf , nread);
46 }
47
48 close(infd);
49 close(outfd);
50
51
52
53 return 0;
54 }
55
结果:
文件的随机读写
- 到目前为止的所有文件访问都是顺序访问。这是因为所有的读和写都从当前文件的偏移位置开始,然后文件偏移值自动地增加到刚好超出读或写结束时的位置,使它为下一次访问作好准备。
- 有个文件偏移这样的机制,在Linux系统中,随机访问就变得很简单,你所需做的只是将当前文件移值改变到有关的位置,它将迫使一次read()或write()发生在这一位置。(除非文件被O_APPEND打开,在这种情况下,任何write调用仍将发生在文件结束处)
lseek
此函数为linux系统调用,对应c库中的fseek
- 功能说明:通过指定相对于开始位置、当前位置或末尾位置的字节数来重定位curp,这取决于lseek()函数中指定的位置
- 原型:
- off_t lseek (int fd,off_t offset,int base);
- 参数
- fd:需设置的文件标识符
- offset:偏移量
- base:搜索的起始位置,见下表
- 返回值:返回新的文件偏移值
base | 文件位置 |
---|---|
SEEK_SET | 从文件开始处计算偏移 |
SEEK_CUR | 从当前文件的偏移值计算偏移 |
SEEK_END | 从文件的结束处计算偏移 |
上述标识在头文件<unistd.h>
例子:
1 /* ************************************************************************
2 > File Name: 02lseek.c
3 > Author: sansuitaibai
4 > email: 2657302908@qq.com
5 > Created Time: 2022年09月18日 18时10分27秒 CST
6 > Description:
7 ************************************************************************/
8 #include<sys/stat.h>
9 #include<sys/types.h>
10 #include<fcntl.h>
11
12 #include<stdio.h>
13 #include<string.h>
14 #include<unistd.h>
15 #include<stdlib.h>
16 #include<errno.h>
17
18 #define ERR_EXIT(m) \
19 do{ \
20 perror(m); \
21 exit(EXIT_FAILURE); \
22 }while(0)
23
24 int main(){
25
26 int fd = open("test.txt",O_RDONLY);
27 if(fd < 0){
28 ERR_EXIT("open");
29 }
30 char buf[5];
31 int nread = 0;
32 nread = read(fd,buf, 5);
33 if(nread <= 0 ){
34 ERR_EXIT("nread<=0");
35 }
36 fprintf(stdout , "%s\n",buf);
37 int nseek = lseek(fd,1,SEEK_CUR);
38 printf("lseek() = %d\n", nseek);
39 nread = read(fd,buf, 5);
40 if(nread <= 0 ){
41 ERR_EXIT("nread<=0");
42 }
43 fprintf(stdout , "%s\n",buf);
44 close(fd);
45
46 return 0;
47 }
48
结果:
lseek()
函数可以移动正在读取文件的当前的指针的位置。
空洞文件hole
1 /* ************************************************************************
2 > File Name: 02lseek.c
3 > Author: sansuitaibai
4 > email: 2657302908@qq.com
5 > Created Time: 2022年09月18日 18时10分27秒 CST
6 > Description:
7 ************************************************************************/
8 #include<sys/stat.h>
9 #include<sys/types.h>
10 #include<fcntl.h>
11
12 #include<stdio.h>
13 #include<string.h>
14 #include<unistd.h>
15 #include<stdlib.h>
16 #include<errno.h>
17
18 #define ERR_EXIT(m) \
19 do{ \
20 perror(m); \
21 exit(EXIT_FAILURE); \
22 }while(0)
23
24 int main(){
25
26 int fd = open("hole.txt",O_RDWR);
27 if(fd < 0){
28 ERR_EXIT("open");
29 }
30 char buf[5];
31 int nread = 0;
32 nread = read(fd,buf, 5);
33 if(nread <= 0 ){
34 ERR_EXIT("nread<=0");
35 }
36 fprintf(stdout , "%s\n",buf);
37 int nseek = lseek(fd,1024*1024*1024,SEEK_CUR);
38 printf("lseek() = %d\n", nseek);
39 if(nread <= 0 ){
40 ERR_EXIT("nread<=0");
41 }
42 if(write(fd ,"HELLO", 5) == -1)
43 ERR_EXIT("wirte:");
44
45 close(fd);
46
47 return 0;
48 }
49
结果:
Linux du (英文全拼:disk usage)命令用于显示目录或文件的大小。
目录访问
opendir
- 功能说明:打开一个目录
- 原型:
- DIR opendir(char*pathname);*
- 参数
- pathname: 路径名
- 返回值:打开成功,返回一个目录指针打开失败,则返回0
readdir
- 功能说明:访问指定目录中下一个连接的细节
- 原型:
- struct dirent readdir(DIR dirptr);
- 参数
- 目录指针
- 返回值:返回一个指向dirent结构的指针,它包含指定目录中下一个连接的细节; 没有更多连接时,返回0
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 */
};
closedir
int closedir(DIR *dirptr);
- 返回值: 成功返回0 ,失败返回-1
chmod和fchmod
- 功能说明:用来改变给定路径名pathname的文件的权限位
int chmod(char* pathname , mode_t mode);
int fchmod(int fd , mode_t mode);
- 返回值: 成功返回0 , 失败返回-1.
- Linux chmod命令
chown和fchown
- 功能说明:用来改变文件所有者的识别号(ownerid)或者它的用户组识别号(group lD)
-
int chown(char* pathname , uid_t owner , gid_t group);
-
int fchown(int fd, uid_t owner ,gid_t group);
-
fd
为文件描述符。 -
返回值: 成功返回0 , 失败返回-1.
rmdir
- 删除一个空目录
int rmdir(char* pathname);
- 返回值: 成功返回0 , 失败返回-1.
mkdir
- 用来创建一个称为
pathname
的新目录,权限为设置为mode
int mkdir(char* pathname , mode_t mode);
- 返回值: 成功返回0 , 失败返回-1.
Linux下DIR,dirent,stat等结构体详解
例子
1 /* ************************************************************************
2 > File Name: 02lseek.c
3 > Author: sansuitaibai
4 > email: 2657302908@qq.com
5 > Created Time: 2022年09月18日 18时10分27秒 CST
6 > Description:
7 ************************************************************************/
8 #include<sys/stat.h>
9 #include<sys/types.h>
13 #include<string.h>
14 #include<unistd.h>
15 #include<stdlib.h>
16 #include<errno.h>
17 #include<dirent.h>
18
19 #define ERR_EXIT(m) \
20 do{ \
21 perror(m); \
22 exit(EXIT_FAILURE); \
23 }while(0)
24
25 int main(){
26
27
28 mkdir("A",0755);
29 mkdir("B",0644);
30 rmdir("A");
31 DIR* dir = opendir(".");
32 struct dirent* de = NULL;
33 while((de = readdir(dir)) != NULL){
34 if(strncmp(de->d_name , "." , 1) == 0)
35 continue;
36 printf("%s\n",de->d_name);
37 }
38 chmod("B",0755);
39 closedir(dir);
40
41
42 return 0;
43 }
44
结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理