linux文件操作函数
生活随笔
收集整理的這篇文章主要介紹了
linux文件操作函数
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
前言:
我們在這一節(jié)將要討論linux下文件操作的各個函數(shù).
文件的創(chuàng)建和讀寫
文件的各個屬性
目錄文件的操作
管道文件
--------------------------------------------------------------------------------
1。文件的創(chuàng)建和讀寫
我假設(shè)你已經(jīng)知道了標(biāo)準(zhǔn)級的文件操作的各個函數(shù)(fopen,fread,fwrite等等).當(dāng)然如果你不清楚的話也不要著急.我們討論的系統(tǒng)級的文件操作實際上是為標(biāo)準(zhǔn)級文件操作服務(wù)的.
當(dāng)我們需要打開一個文件進(jìn)行讀寫操作的時候,我們可以使用系統(tǒng)調(diào)用函數(shù)open.使用完成以后我們調(diào)用另外一個close函數(shù)進(jìn)行關(guān)閉操作.
#include
#include
#include
#include
int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
int close(int fd);
open函數(shù)有兩個形式.其中pathname是我們要打開的文件名(包含路徑名稱,缺省是認(rèn)為在當(dāng)前路徑下面).flags可以去下面的一個值或者是幾個值的組合.
O_RDONLY:以只讀的方式打開文件.
O_WRONLY:以只寫的方式打開文件.
O_RDWR:以讀寫的方式打開文件.
O_APPEND:以追加的方式打開文件.
O_CREAT:創(chuàng)建一個文件.
O_EXEC:如果使用了O_CREAT而且文件已經(jīng)存在,就會發(fā)生一個錯誤.
O_NOBLOCK:以非阻塞的方式打開一個文件.
O_TRUNC:如果文件已經(jīng)存在,則刪除文件的內(nèi)容.
前面三個標(biāo)志只能使用任意的一個.如果使用了O_CREATE標(biāo)志,那么我們要使用open的第二種形式.還要指定mode標(biāo)志,用來表示文件的訪問權(quán)限.mode可以是以下情況的組合.
-----------------------------------------------------------------
S_IRUSR????????用戶可以讀?????S_IWUSR????????用戶可以寫
S_IXUSR????????用戶可以執(zhí)行???S_IRWXU????????用戶可以讀寫執(zhí)行
-----------------------------------------------------------------
S_IRGRP????????組可以讀???????S_IWGRP????????組可以寫
S_IXGRP????????組可以執(zhí)行?????S_IRWXG????????組可以讀寫執(zhí)行
-----------------------------------------------------------------
S_IROTH?????????其他人可以讀????S_IWOTH?????????其他人可以寫
S_IXOTH?????????其他人可以執(zhí)行??S_IRWXO?????????其他人可以讀寫執(zhí)行
-----------------------------------------------------------------
S_ISUID????????設(shè)置用戶執(zhí)行ID??S_ISGID???????????????設(shè)置組的執(zhí)行ID
-----------------------------------------------------------------
我們也可以用數(shù)字來代表各個位的標(biāo)志.Linux總共用5個數(shù)字來表示文件的各種權(quán)限.
00000.第一位表示設(shè)置用戶ID.第二位表示設(shè)置組ID,第三位表示用戶自己的權(quán)限位,第四位表示組的權(quán)限,最后一位表示其他人的權(quán)限.
每個數(shù)字可以取1(執(zhí)行權(quán)限),2(寫權(quán)限),4(讀權(quán)限),0(什么也沒有)或者是這幾個值的和.
比如我們要創(chuàng)建一個用戶讀寫執(zhí)行,組沒有權(quán)限,其他人讀執(zhí)行的文件.設(shè)置用戶ID位那么我們可以使用的模式是--1(設(shè)置用戶ID)0(組沒有設(shè)置)7(1+2+4)0(沒有權(quán)限,使用缺省)5(1+4)即10705:
open("temp",O_CREAT,10705);
如果我們打開文件成功,open會返回一個文件描述符.我們以后對文件的所有操作就可以對這個文件描述符進(jìn)行操作了.
當(dāng)我們操作完成以后,我們要關(guān)閉文件了,只要調(diào)用close就可以了,其中fd是我們要關(guān)閉的文件描述符.
文件打開了以后,我們就要對文件進(jìn)行讀寫了.我們可以調(diào)用函數(shù)read和write進(jìn)行文件的讀寫.
#include
ssize_t??read(int fd, void *buffer,size_t count);
ssize_t write(int fd, const void *buffer,size_t count);
fd是我們要進(jìn)行讀寫操作的文件描述符,buffer是我們要寫入文件內(nèi)容或讀出文件內(nèi)容的內(nèi)存地址.count是我們要讀寫的字節(jié)數(shù).
對于普通的文件read從指定的文件(fd)中讀取count字節(jié)到buffer緩沖區(qū)中(記住我們必須提供一個足夠大的緩沖區(qū)),同時返回count.
如果read讀到了文件的結(jié)尾或者被一個信號所中斷,返回值會小于count.如果是由信號中斷引起返回,而且沒有返回數(shù)據(jù),read會返回-1,且設(shè)置errno為EINTR.當(dāng)程序讀到了文件結(jié)尾的時候,read會返回0.
write從buffer中寫count字節(jié)到文件fd中,成功時返回實際所寫的字節(jié)數(shù).
下面我們學(xué)習(xí)一個實例,這個實例用來拷貝文件.
#include
#include
#include
#include
#include
#include
#include
#define????????BUFFER_SIZE????1024
int main(int argc,char **argv)
{
int from_fd,to_fd;
int bytes_read,bytes_write;
char buffer[BUFFER_SIZE];
char *ptr;
if(argc!=3)
{
fprintf(stderr,"Usage:%s fromfile tofile\n\a",argv[0]);
exit(1);
}
/*??????打開源文件?????*/
if((from_fd=open(argv[1],O_RDONLY))==-1)
{
fprintf(stderr,"Open %s Error:%s\n",argv[1],strerror(errno));
exit(1);
}
/*??????創(chuàng)建目的文件???*/
if((to_fd=open(argv[2],O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))==-1)
{
fprintf(stderr,"Open %s Error:%s\n",argv[2],strerror(errno));
exit(1);
}
/*??????以下代碼是一個經(jīng)典的拷貝文件的代碼????*/
while(bytes_read=read(from_fd,buffer,BUFFER_SIZE))
{
/*??????一個致命的錯誤發(fā)生了???*/
if((bytes_read==-1)&&(errno!=EINTR)) break;
else if(bytes_read>0)
{
ptr=buffer;
while(bytes_write=write(to_fd,ptr,bytes_read))
{
/*??????一個致命錯誤發(fā)生了?????*/
if((bytes_write==-1)&&(errno!=EINTR))break;
/*??????寫完了所有讀的字節(jié)?????*/
else if(bytes_write==bytes_read) break;
/*??????只寫了一部分,繼續(xù)寫????*/
else if(bytes_write>0)
{
ptr+=bytes_write;
bytes_read-=bytes_write;
}
}
/*??????寫的時候發(fā)生的致命錯誤?*/
if(bytes_write==-1)break;
}
}
close(from_fd);
close(to_fd);
exit(0);
}
2。文件的各個屬性
文件具有各種各樣的屬性,除了我們上面所知道的文件權(quán)限以外,文件還有創(chuàng)建時間,大小等等屬性.
有時侯我們要判斷文件是否可以進(jìn)行某種操作(讀,寫等等).這個時候我們可以使用access函數(shù).
#include
int access(const char *pathname,int mode);
pathname:是文件名稱,mode是我們要判斷的屬性.可以取以下值或者是他們的組合.
R_OK文件可以讀,W_OK文件可以寫,X_OK文件可以執(zhí)行,F_OK文件存在.當(dāng)我們測試成功時,函數(shù)返回0,否則如果有一個條件不符時,返回-1.
如果我們要獲得文件的其他屬性,我們可以使用函數(shù)stat或者fstat.
#include
#include
int stat(const char *file_name,struct stat *buf);
int fstat(int filedes,struct stat *buf);
struct stat {
dev_t??????????st_dev;????????/*?設(shè)備???*/
ino_t??????????st_ino;????????/*?節(jié)點???*/??
mode_t?????????st_mode;???????/*?模式???*/
nlink_t????????st_nlink;??????/*?硬連接?*/
uid_t??????????st_uid;????????/*?用戶ID */
gid_t??????????st_gid;????????/*?組ID???*/
dev_t??????????st_rdev;???????/*?設(shè)備類型?*/
off_t??????????st_off;????????/*?文件字節(jié)數(shù)?*/
unsigned long?st_blksize;????/*?塊大小?*/
unsigned long??st_blocks;?????/*?塊數(shù)???*/
time_t?????????st_atime;??????/*?最后一次訪問時間?*/
time_t?????????st_mtime;??????/*?最后一次修改時間?*/
time_t?????????st_ctime;??????/*?最后一次改變時間(指屬性) */
};
stat用來判斷沒有打開的文件,而fstat用來判斷打開的文件.我們使用最多的屬性是st_mode.通過著屬性我們可以判斷給定的文件是一個普通文件還是一個目錄,連接等等.可以使用下面幾個宏來判斷.
S_ISLNK(st_mode):是否是一個連接.S_ISREG是否是一個常規(guī)文件.S_ISDIR是否是一個目錄S_ISCHR是否是一個字符設(shè)備.S_ISBLK是否是一個塊設(shè)備S_ISFIFO是否 是一個FIFO文件.S_ISSOCK是否是一個SOCKET文件.?我們會在下面說明如何使用這幾個宏的.
3。目錄文件的操作
在我們編寫程序的時候,有時候會要得到我們當(dāng)前的工作路徑。C庫函數(shù)提供了getcwd來解決這個問題。
#include
char *getcwd(char *buffer,size_t size);
我們提供一個size大小的buffer,getcwd會把我們當(dāng)前的路徑考到buffer中.如果buffer太小,函數(shù)會返回-1和一個錯誤號.
Linux提供了大量的目錄操作函數(shù),我們學(xué)習(xí)幾個比較簡單和常用的函數(shù).
#include
#include
#include
#include
#include
int mkdir(const char *path,mode_t mode);
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dir);
void rewinddir(DIR *dir);
off_t telldir(DIR *dir);
void??seekdir(DIR *dir,off_t off);
int closedir(DIR *dir);
struct dirent {
long????d_ino;
off_t???d_off;
unsigned short d_reclen;
char????d_name[NAME_MAX+1];????/*?文件名稱????*/
mkdir很容易就是我們創(chuàng)建一個目錄,opendir打開一個目錄為以后讀做準(zhǔn)備.readdir讀一個打開的目錄.rewinddir是用來重讀目錄的和我們學(xué)的rewind函數(shù)一樣.closedir是關(guān)閉一個目錄.telldir和seekdir類似與ftee和fseek函數(shù).
下面我們開發(fā)一個小程序,這個程序有一個參數(shù).如果這個參數(shù)是一個文件名,我們輸出這個文件的大小和最后修改的時間,如果是一個目錄我們輸出這個目錄下所有文件的大小和修改時間.
#include
#include
#include
#include
#include
#include
#include
static int get_file_size_time(const char *filename)
{
struct stat statbuf;
if(stat(filename,&statbuf)==-1)
{
printf("Get stat on %s Error:%s\n",
filename,strerror(errno));
return(-1);
}
if(S_ISDIR(statbuf.st_mode))return(1);
if(S_ISREG(statbuf.st_mode))
printf("%s size:%ld bytes\tmodified at %s",
filename,statbuf.st_size,ctime(&statbuf.st_mtime));??
return(0);
}
int main(int argc,char **argv)
{
DIR *dirp;
struct dirent *direntp;
int stats;
if(argc!=2)
{
printf("Usage:%s filename\n\a",argv[0]);
exit(1);
}
if(((stats=get_file_size_time(argv[1]))==0)||(stats==-1))exit(1);
if((dirp=opendir(argv[1]))==NULL)
{
printf("Open Directory %s Error:%s\n",
argv[1],strerror(errno));
exit(1);
}
while((direntp=readdir(dirp))!=NULL)
if(get_file_size_time(direntp-< cat Linux提供了許多的過濾和重定向程序,比如more 4。管道文件?} exit(1); closedir(dirp);> | <<等等重定向操作符.在這些過濾和重 定向程序當(dāng)中,都用到了管道這種特殊的文件.系統(tǒng)調(diào)用pipe可以創(chuàng)建一個管道.
#include
int pipe(int fildes[2]);
pipe調(diào)用可以創(chuàng)建一個管道(通信緩沖區(qū)).當(dāng)調(diào)用成功時,我們可以訪問文件描述符fildes[0],fildes[1].其中fildes[0]是用來讀的文件描述符,而fildes[1]是用來寫的文件描述符.
在實際使用中我們是通過創(chuàng)建一個子進(jìn)程,然后一個進(jìn)程寫,一個進(jìn)程讀來使用的.
關(guān)于進(jìn)程通信的詳細(xì)情況請查看進(jìn)程通信
#include
#include
#include
#include
#include
#include
#include
#define??BUFFER????????255
int main(int argc,char **argv)
{
char buffer[BUFFER+1];
int fd[2];
if(argc!=2)
{
fprintf(stderr,"Usage:%s string\n\a",argv[0]);
exit(1);
}
if(pipe(fd)!=0)
{
fprintf(stderr,"Pipe Error:%s\n\a",strerror(errno));
exit(1);
}
if(fork()==0)
{
close(fd[0]);
printf("Child[%d] Write to pipe\n\a",getpid());
snprintf(buffer,BUFFER,"%s",argv[1]);
write(fd[1],buffer,strlen(buffer));
printf("Child[%d] Quit\n\a",getpid());
exit(0);
}
else
{
close(fd[1]);
printf("Parent[%d] Read from pipe\n\a",getpid());
memset(buffer,'\0',BUFFER+1);
read(fd[0],buffer,BUFFER);
printf("Parent[%d] Read:%s\n",getpid(),buffer);
exit(1);
}
}
為了實現(xiàn)重定向操作,我們需要調(diào)用另外一個函數(shù)dup2.
#include
int dup2(int oldfd,int newfd);
dup2將用oldfd文件描述符來代替newfd文件描述符,同時關(guān)閉newfd文件描述符.也就是說,
所有向newfd操作都轉(zhuǎn)到oldfd上面.下面我們學(xué)習(xí)一個例子,這個例子將標(biāo)準(zhǔn)輸出重定向到一個文件.
#include
#include
#include
#include
#include
#include
#include
#define??BUFFER_SIZE???1024
int main(int argc,char **argv)
{
int fd;
char buffer[BUFFER_SIZE];
if(argc!=2)
{
fprintf(stderr,"Usage:%s outfilename\n\a",argv[0]);
exit(1);
}
if((fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1)
{
fprintf(stderr,"Open %s Error:%s\n\a",argv[1],strerror(errno));
exit(1);
}
if(dup2(fd,STDOUT_FILENO)==-1)
{
fprintf(stderr,"Redirect Standard Out Error:%s\n\a",strerror(errno));
exit(1);
}
fprintf(stderr,"Now,please input string");
fprintf(stderr,"(To quit use CTRL+D)\n");?
while(1)
{
fgets(buffer,BUFFER_SIZE,stdin);
if(feof(stdin))break;
write(STDOUT_FILENO,buffer,strlen(buffer));
}
exit(0);
}
好了,文件一章我們就暫時先討論到這里,學(xué)習(xí)好了文件的操作我們其實已經(jīng)可以寫出一些比較有用的程序了.我們可以編寫一個實現(xiàn)例如dir,mkdir,cp,mv等等常用的文件操作命令了.
想不想自己寫幾個試一試呢?
前言:Linux下的時間概念
這一章我們學(xué)習(xí)Linux的時間表示和計算函數(shù)
時間的表示
時間的測量
計時器的使用
1。時間表示?????在程序當(dāng)中,我們經(jīng)常要輸出系統(tǒng)當(dāng)前的時間,比如我們使用date命令的輸出結(jié)果.這個時候我們可以使用下面兩個函數(shù)
#include
time_t??time(time_t *tloc);
char????*ctime(const time_t *clock);
time函數(shù)返回從1970年1月1日0點以來的秒數(shù).存儲在time_t結(jié)構(gòu)之中.不過這個函數(shù)的返回值對于我們來說沒有什么實際意義.這個時候我們使用第二個函數(shù)將秒數(shù)轉(zhuǎn)化為字符串.?這個函數(shù)的返回類型是固定的:一個可能值為. Thu Dec 7 14:58:59 2000?這個字符串的長度是固定的為26
2。時間的測量?????有時候我們要計算程序執(zhí)行的時間.比如我們要對算法進(jìn)行時間分析.這個時候可以使用下面這個函數(shù).
#include
int gettimeofday(struct timeval *tv,struct timezone *tz);
strut timeval {
long????tv_sec;????????/*??????秒數(shù)???????????*/
long????tv_usec;???????/*??????微秒數(shù)?????????*/
};
gettimeofday將時間保存在結(jié)構(gòu)tv之中.tz一般我們使用NULL來代替.
#include?
int getitimer(int which,struct itimerval *value);
int setitimer(int which,struct itimerval *newval, struct itimerval *oldval); struct itimerval { struct timeval it_interval; struct timeval it_value; } getitimer函數(shù)得到間隔計時器的時間值.保存在value中?setitimer函數(shù)設(shè)置間隔計時器的時間值為newval.并將舊值保存在oldval中. which表示使用三個計時器中的哪一個. itimerval結(jié)構(gòu)中的it_value是減少的時間,當(dāng)這個值為0的時候就發(fā)出相應(yīng)的信號了.?然后設(shè)置為it_interval值. #include #include #include #include #include #define????????PROMPT??"時間已經(jīng)過去了兩秒鐘\n\a" char *prompt=PROMPT; unsigned int len; void prompt_info(int signo) { write(STDERR_FILENO,prompt,len); } void init_sigaction(void) { struct sigaction act; act.sa_handler=prompt_info; act.sa_flags=0; sigemptyset(&act.sa_mask); sigaction(SIGPROF,&act,NULL); } void init_time() { struct itimerval value; value.it_value.tv_sec=2; value.it_value.tv_usec=0; value.it_interval=value.it_value; setitimer(ITIMER_PROF,&value,NULL); } int main() { len=strlen(prompt); init_sigaction(); init_time(); while(1); exit(0); }總結(jié)
以上是生活随笔為你收集整理的linux文件操作函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 改变PPT导出图片分辨率
- 下一篇: 物联网卡安全吗?