一、Xmind整理:
文件描述符概念:
二、課上練習(xí):
練習(xí)1:用fread和fwrite實(shí)現(xiàn)文件拷貝?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
//以讀的方式打開源文件
FILE* fp_r=fopen("./01_fopen.c","r");
if(NULL==fp_r)
{
ERR_MSG("fopen");
return -1;
}
//以寫的方式打開源文件
FILE* fp_w=fopen("./copy.c","w");
if(NULL==fp_w)
{
ERR_MSG("fopen");
return -1;
}
//讀一次寫一次,直到文件讀取完畢
char buf[128]="";
size_t res=0;
while(1)
{
bzero(buf,sizeof(buf));
//以128為單位,讀取1個(gè)數(shù)據(jù),所當(dāng)不足128的時(shí)候
//剩下的數(shù)據(jù)讀取不出來(lái),所以這個(gè)代碼是錯(cuò)誤的
res=fread(buf,1,sizeof(buf),fp_r);
printf("res=%ld\n",res);
if(0==res)
break;
fwrite(buf,1,res,fp_w);
}
printf("拷貝完畢\n");
//關(guān)閉
fclose(fp_w);
fclose(fp_r);
return 0;
}
練習(xí)2:time
功能:從1970-1-1日至今的秒數(shù)
原型:
#include <time.h>
time_t time(time_t *tloc);
參數(shù):
time_t *tloc:若不為空,則1970-1-1日至今的秒數(shù)同樣會(huì)被存儲(chǔ)到該指針指向的內(nèi)存空間中;
返回值:
成功,返回1970-1-1日至今的秒數(shù);
失敗,返回((time_t) -1),更新errno;
time_t t = time(NULL);
printf("%ld\n", t);
time_t pt;
time(&pt);
printf("%ld\n", pt);
練習(xí)3:localtime
功能:將1970-1-1日至今的秒數(shù)轉(zhuǎn)換成日歷格式
原型:
#include <time.h>
struct tm *localtime(const time_t *timep);
參數(shù):
time_t *timep: 指定要轉(zhuǎn)換成日歷格式的秒數(shù)的首地址;
返回值:
成功,返回結(jié)構(gòu)體指針; vi -t tm可以查看struct tm 成員 或者man手冊(cè)往下翻
失敗,返回NULL;更新errno;
struct tm {
int tm_sec; /* Seconds (0-60) */ 秒
int tm_min; /* Minutes (0-59) */ 分
int tm_hour; /* Hours (0-23) */ 時(shí)
int tm_mday; /* Day of the month (1-31) */ 日
int tm_mon; /* Month (0-11) */ 月= tm_mon+1
int tm_year; /* Year - 1900 */ 年= tm_year+1900
int tm_wday; /* Day of the week (0-6, Sunday = 0) */ 星期
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */ 一年中的第幾天
};
例題:?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <head.h>
int main(int argc, const char *argv[])
{
/*
time_t t=time(NULL);
printf("%ld\n",t);
time _t pt;
time(&pt);
printf("%d\n",pt);
*/
time_t t;
struct tm* info=NULL;
while(1)
{
t=time(NULL);
info=localtime(&t);
printf("%d-%02d-%02d %02d:%02d:%02d\r",\
info->tm_year+1900,info->tm_mon+1,info->tm_mday,\
info->tm_hour,info->tm_min,info->tm_sec);
fflush(stdout);
sleep(1);
}
return 0;
}
練習(xí)4:文件描述符的總量
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
printf("%d %d %d\n",stdin->_fileno,stdout->_fileno,stderr->_fileno);
FILE*fp=NULL;
while(1)
{
fp=fopen("./1.txt","w");
if(NULL==fp)
{
ERR_MSG("fopen");
return -1;
}
printf("%d ",fp->_fileno);
fflush(stdout);
}
return 0;
}
練習(xí)5:open
功能:打開一個(gè)文件
原型:
#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);
參數(shù):
char *pathname:指定要打開的文件的路徑和名字;
int flags:打開方式
O_RDONLY 只讀,
O_WRONLY 只寫,
O_RDWR 讀寫
----以上三種必須包含一種----------
O_APPEND 追加方式打開,
O_TRUNC 清空,若文件存在,且是一個(gè)普通文件,且以寫的方式打開
O_CREAT 若文件不存在,則創(chuàng)建一個(gè)普通文件。
若有多個(gè)選項(xiàng)合成一個(gè)打開方式,則用按位或連接:
"w":O_WRONLY | O_CREAT | O_TRUNC
mode_t mode:用來(lái)指定文件創(chuàng)建的時(shí)候的權(quán)限,例如:0664
若flags中包含了O_CREAT或者O_TMPFILE的時(shí)候,就必須寫mode參數(shù);
若flags沒有O_CREAT或者O_TMPFILE的時(shí)候,會(huì)忽略mode參數(shù);
返回值:
成功,返回文件描述符,
失敗,返回-1,更新errno;
注意:
標(biāo)準(zhǔn)IO中的 r r+ w w+ a a+,用文件IO中的flags進(jìn)行組合。
?
練習(xí)6:umask
the mode of the created file is (mode & ~umask).
文件創(chuàng)建時(shí)候的真實(shí)權(quán)限是 mode & ~umask
mode: 0777 -> 111 111 111 umask?111 111 101=> ~umask -> umask = 000 000 010 = 0002
結(jié)果: 0775 ----> 111 111 101
i. umask是什么
文件權(quán)限掩碼,目的就是影響文件創(chuàng)建時(shí)候的權(quán)限。可以通過(guò)設(shè)置umask的值保證某些用戶肯定沒有某些權(quán)限。
ii. 獲取umask的值
終端輸入:umask
iii. 修改umask的值
1.終端輸入: umask 0 只在設(shè)置終端有效
2.umask()函數(shù)
#include <sys/types.h> #include <sys/stat.h> mode_t umask(mode_t mask); umask(0);
練習(xí)7:close
功能:關(guān)閉文件; 釋放文件描述符
原型:
#include <unistd.h>
int close(int fd);
參數(shù):
int fd:指定要關(guān)閉的文件描述符;
返回值:
成功,返回0;
失敗,返回-1,更新errno;
練習(xí)8:write
功能:將數(shù)據(jù)寫入到文件中
原型:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
參數(shù):
int fd:指定要將數(shù)據(jù)寫入到哪個(gè)文件中,填對(duì)應(yīng)的文件描述符;
void *buf:指定要輸出的數(shù)據(jù)的首地址,可以是任意類型數(shù)據(jù);
size_t count:指定要輸出的數(shù)據(jù)字節(jié)數(shù);
返回值:
成功,返回成功輸出的字節(jié)數(shù);
失敗,返回-1,更新errno;
?例題:?創(chuàng)建一個(gè)權(quán)限是0777的文件,并在數(shù)據(jù)寫入到文件中
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
//將本程序的umask的值修改成0
umask(0);
int fd=open("./open.txt",O_WRONLY|O_CREAT|O_TRUNC,0777);
if(fd<0)
{
ERR_MSG("open");
return -1;
}
printf("open success\n");
ssize_t res=0;
char buf[]="hello world";
res=write(fd,buf,sizeof(buf));
printf("res=%ld\n",res);
if(close(fd)<0)
{
ERR_MSG("close");
return -1;
}
printf("close success\n");
return 0;
}
注意:?
write函數(shù)指定寫多少個(gè)字節(jié),就會(huì)從內(nèi)存中拿多少個(gè)字節(jié),寫入到文件中,即使越界
練習(xí)9:read
功能:從文件中讀取數(shù)據(jù)
原型:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
參數(shù):
int fd:指定要從哪個(gè)文件中讀取數(shù)據(jù),填對(duì)應(yīng)的文件描述符;
void *buf:指定要將讀取到的數(shù)據(jù)存儲(chǔ)到那塊空間中,可以是任意類型數(shù)據(jù);
size_t count:指定要讀取的數(shù)據(jù)字節(jié)數(shù);
返回值:
>0, 成功,返回成功讀取的字節(jié)數(shù);
=0, 文件讀取完畢;
=-1, 失敗,返回-1,更新errno;
?例題1:?read的使用
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
//將本程序的umask的值修改成0
umask(0);
int fd=open("./01_fileno.c",O_RDONLY);
if(fd<0)
{
ERR_MSG("open");
return -1;
}
printf("open success\n");
ssize_t res=0;
char buf[128]="";
while(1)
{
bzero(buf,sizeof(buf));
res=read(fd,buf,sizeof(buf));
if(0==res)
{
break;
}
//將數(shù)據(jù)寫到終端,寫的個(gè)數(shù)為實(shí)際讀取到的字節(jié)數(shù)
write(1,buf,res);
}
#if 0
while(1)
{
bzero(buf,sizeof(buf));
/***************************************/
//由于后續(xù)打印的是使用%s打印,所以需要保留一個(gè)\0位置
//防止%s打印的時(shí)候越界少\0位
res=read(fd,buf,sizeof(buf)-1);
if(0==res)
{
break;
}
printf("%s",buf); //%s打印直到遇到\0位置
}
#endif
printf("讀取完畢\n");
if(close(fd)<0)
{
ERR_MSG("close");
return -1;
}
printf("close success\n");
return 0;
}
?例題2:用read和write函數(shù)實(shí)現(xiàn),拷貝圖片
?提示:1.ls-l查看圖片類型
? ? ? ? ? ? 2.eog? 圖片--->打開圖片
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
//以讀的方式打開源文件
int fd_r=open("./1.png",O_RDONLY);
if(fd_r<0)
{
ERR_MSG("open");
return -1;
}
printf("open success\n");
//以寫的方式打開目標(biāo)文件
int fd_w=open("./2.png",O_WRONLY|O_CREAT|O_TRUNC,0664);
if(fd_w<0)
{
ERR_MSG("open");
return -1;
}
ssize_t res=0;
char buf[128]="";
//讀一次寫一次
while(1)
{
bzero(buf,sizeof(buf));
res=read(fd_r,buf,sizeof(buf));
if(0==res)
{
break;
}
//讀多少個(gè)就寫多少個(gè)
if(write(fd_w,buf,res)<0)
{
ERR_MSG("write");
return -1;
}
}
printf("拷貝完成\n");
//關(guān)閉
if(close(fd_r)<0)
{
ERR_MSG("close");
return -1;
}
if(close(fd_w)<0)
{
ERR_MSG("close");
return -1;
}
printf("close success\n");
return 0;
}
練習(xí)10:lseek
功能:修改文件偏移量
原型:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
參數(shù):
int fd:文件描述符;
off_t offset: 距離whence參數(shù)指定的偏移量。往前偏移填負(fù)數(shù), 往后偏移填正數(shù)
int whence:
SEEK_SET, 文件開頭位置
SEEK_CUR, 文件當(dāng)前位置
SEEK_END 文件結(jié)尾位置
返回值:
成功,修改偏移量后,文件當(dāng)前位置距離文件開頭的偏移量;
失敗,返回-1,更新errno;
//計(jì)算文件大小
off_t size = lseek(fd_r, 0, SEEK_END);
printf("size=%ld\n", size);
例題:lseek的使用?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
//以讀的方式打開源文件
int fd_r=open("./1.png",O_RDONLY);
if(fd_r<0)
{
ERR_MSG("open");
return -1;
}
//計(jì)算文件大小
off_t size=lseek(fd_r,0,SEEK_END);
printf("size=%ld\n",size);
//關(guān)閉
close(fd_r);
return 0;
}
注意:?
若偏移量在文件開頭,能否繼續(xù)往前偏移 --->?不行
若偏移量在文件結(jié)尾,能否繼續(xù)往后偏移 ---> 可以
練習(xí)11:獲取文件屬性
練習(xí)12:stat
功能:獲取文件的屬性
原型:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);
參數(shù):
char *pathname:指定要獲取屬性的文件路徑以及名字;
struct stat *statbuf:存儲(chǔ)獲取到的屬性;
返回值:
成功,返回0;
失敗,返回-1,更新errno;
vi -t stat 或者 man手冊(cè)往下翻
struct stat
{
ino_t st_ino; /* Inode number */ inode號(hào)
mode_t st_mode; /* File type and mode */ 文件類型和權(quán)限
nlink_t st_nlink; /* Number of hard links */ 硬鏈接數(shù)
uid_t st_uid; /* User ID of owner */ 用戶的uid
gid_t st_gid; /* Group ID of owner */ 組用戶的gid
off_t st_size; /* Total size, in bytes */ 文件大小
struct timespec st_atim; /* Time of last access */ 最后一次被訪問(wèn)的時(shí)間
struct timespec st_mtim; /* Time of last modification */ 最后一次被修改的時(shí)間
struct timespec st_ctim; /* Time of last status change */ 最后一次改變狀態(tài)的時(shí)間
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
提取文件的權(quán)限:
mode_t st_mode 本質(zhì)上是一個(gè)unsigned int類型,里面存儲(chǔ)了文件的類型和權(quán)限。
st_mode中其中低9bits存儲(chǔ)了文件的權(quán)限:[0bit - 8bit]
例題:文件權(quán)限提取?
#include <stdio.h>
#include <head.h>
void get_filePermission(mode_t m) //mode_t m = buf.st_mode
{
if((m & 0400) != 0)
putchar('r');
else
putchar('-');
if((m & 0200) != 0)
putchar('w');
else
putchar('-');
if((m & 0100) != 0)
putchar('x');
else
putchar('-');
///
if((m & 0040) != 0)
putchar('r');
else
putchar('-');
if((m & 0020) != 0)
putchar('w');
else
putchar('-');
if((m & 0010) != 0)
putchar('x');
else
putchar('-');
if((m & 0004) != 0)
putchar('r');
else
putchar('-');
if((m & 0002) != 0)
putchar('w');
else
putchar('-');
if((m & 0001) != 0)
putchar('x');
else
putchar('-');
return;
}
int main(int argc, const char *argv[])
{
struct stat buf;
if(stat("./01_fileno.c", &buf) < 0)
{
ERR_MSG("stat");
return -1;
}
//文件的類型和權(quán)限
printf("mode: 0%o\n", buf.st_mode);
get_filePermission(buf.st_mode);
//文件的硬鏈接數(shù)
printf("link: %ld\n", buf.st_nlink);
//文件的所屬用戶
printf("uid: %d\n", buf.st_uid);
//文件所屬組用戶
printf("gid: %d\n", buf.st_gid);
//文件大小
printf("size: %ld\n", buf.st_size);
//文件的修改時(shí)間
printf("time: %ld\n", buf.st_ctime);
//文件的名字
return 0;
}
三、課后作業(yè):
1.用read函數(shù)計(jì)算文件的大小?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
int main(int argc, const char *argv[])
{
int fd = open("./1.png",O_RDONLY);
if(fd < 0)
{
ERR_MSG("open");
return -1;
}
printf("open success\n");
off_t size = lseek(fd,0,SEEK_END);
printf("size=%ld\n",size);
char c;
ssize_t res = 0;
int count = 0;
lseek(fd,0,SEEK_SET);
while(1)
{
res = read(fd,&c,1);
if(0 == res)
break;
count++;
}
printf("count=%d\n",count);
if(close(fd) < 0)
{
ERR_MSG("close");
return -1;
}
printf("close success\n");
return 0;
}
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-621278.html
2.將課上的文件權(quán)限提取修改成循環(huán)方式
#include <stdio.h>
#include <head.h>
void get_filePermission(mode_t m)
{
long x=0400;
char c[]="rwx";
int count=0;
while(x)
{
if((m & x) != 0)
putchar('r');
else
putchar('-');
x=x>>1;
if((m & x) != 0)
putchar('w');
else
putchar('-');
x=x>>1;
if((m & x) != 0)
putchar('x');
else
putchar('-');
x=x>>1;
}
return;
}
int main(int argc, const char *argv[])
{
struct stat buf;
if(stat("./01_fileno.c", &buf) < 0)
{
ERR_MSG("stat");
return -1;
}
//文件的類型和權(quán)限
printf("mode: 0%o\n", buf.st_mode);
get_filePermission(buf.st_mode);
//文件的硬鏈接數(shù)
printf("link: %ld\n", buf.st_nlink);
//文件的所屬用戶
printf("uid: %d\n", buf.st_uid);
//文件所屬組用戶
printf("gid: %d\n", buf.st_gid);
//文件大小
printf("size: %ld\n", buf.st_size);
//文件的修改時(shí)間
printf("time: %ld\n", buf.st_ctime);
return 0;
}
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-621278.html
到了這里,關(guān)于IO進(jìn)程線程day3(2023.7.31)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!