获取、改变当前目录:
原型为:
#include <unistd.h> //头文件
char *getcwd(char *buf, size_t size); //获取当前目录,相当于pwd命令
int chdir(const char *path); //修改当前目录,即切换目录,相当于cd命令
其中getcwd()函数:将当前的工作目录绝对路径复制到参数buf所指的内存空间,参数size为buf的空间大小. 在调用此函数时,buf所指的内存空间要足够大,若工作目录绝对路径的字符串长度超过参数size大小,则回值NULL,errno的值则为ERANGE。倘若参数buf为NULL,getcwd()会依参数size的大小自动配置内存(使用malloc()),如果参数size也为0,则getcwd()会依工作目录绝对路径的字符串程度来决定所配置的内存大小,进程可以在使用完此字符串后自动利用free()来释放此空间。所以常用的形式:getcwd(NULL, 0);
#include<unistd.h> main() { chdir(“/tmp”); printf(“current working directory: %s\n”,getcwd(NULL,0)); }
获取目录信息:
原型为:
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name); //打开一个目录
struct dirent *readdir(DIR *dir); //读取目录的一项信息,并返回该项信息的结构体指针
void rewinddir(DIR *dir); //重新定位到目录文件的头部
void seekdir(DIR *dir,off_t offset);//用来设置目录流目前的读取位置
off_t telldir(DIR *dir); //返回目录流当前的读取位置
int closedir(DIR *dir); //关闭目录文件
读取目录信息的步骤为:
用opendir函数打开目录;
使用readdir函数迭代读取目录的内容,如果已经读取到目录末尾,又想重新开始读,则可以使用rewinddir函数将文件指针重新定位到目录文件的起始位置;
用closedir函数关闭目录
opendir()用来打开参数name指定的目录,并返回DIR*形态的目录流,和文件操作函数open()类似,接下来对目录的读取和搜索都要使用此返回值。函数失败则返回NULL;
readdir()函数用来读取目录的信息,并返回一个结构体指针,该指针保存了目录的相关信息。有错误发生或者读取到目录文件尾则返回NULL。
dirent结构体如下:
struct dirent { ino_t d_ino; /* inode number(此目录进入点的inode) */ off_t d_off; /* offset to the next dirent(目录开头到进入点的位移 */ unsigned short d_reclen; /* length of this record(目录名的长度) */ unsigned char d_type; /* type of file(所指的文件类型) */ char d_name[256]; /* filename(文件名) */ };
获取文件信息:
可以通过fstat和stat函数获取文件信息,调用完毕后,文件信息被填充到结构体struct stat变量中,函数原型为:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name, struct stat *buf); //文件名 通过文件名获取文件各种属性
经常与opendir(),readdir()结合使用
int fstat(int fd, struct stat *buf); //文件描述词 stat结构体指针
结构体stat的定义为:
struct stat { dev_t st_dev; /*如果是设备,返回设备表述符,否则为0*/ ino_t st_ino; /* i节点号 */ mode_t st_mode; /* 文件类型 */ nlink_t st_nlink; /* 链接数 */ uid_t st_uid; /* 属主ID */ gid_t st_gid; /* 组ID */ dev_t st_rdev; /* 设备类型*/ off_t st_size; /* 文件大小,字节表示 */ blksize_t st_blksize; /* 块大小*/ blkcnt_t st_blocks; /* 块数 */ time_t st_atime; /* 最后访问时间*/ time_t st_mtime; /* 最后修改时间*/ time_t st_ctime; /* 创建时间 */ };
以上的函数结合使用模拟一个ls -l的功能
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <stdlib.h> #include <unistd.h> #include <time.h> #include <pwd.h> #include <grp.h> void mode_to_str(mode_t md, char* str) ; void format(char* p) ; int main(int argc, char* argv[]) { DIR* pDir ; char* ptm ; struct stat mystat ; struct dirent* myent; char str_mode[11]=""; int col = 0 ; if(argc == 1) { pDir = opendir("."); }else { pDir = opendir(argv[1]); } if(pDir == NULL) { perror("open dir fail: "); exit(-1); } printf("nlink,mode,uid,gid,size,atime,name\n"); while( (myent = readdir(pDir) ) != NULL ) { memset(&mystat, 0, sizeof(mystat)); stat(myent ->d_name, &mystat); memset(str_mode,0, 11); mode_to_str(mystat.st_mode,str_mode); ptm = ctime(&mystat.st_atime); format(ptm); if(strncmp(myent ->d_name, ".",1) !=0 && strncmp(myent->d_name,"..",2)!=0) { printf("%10s.%2d %-5s %-5s %5d %s %s\n",str_mode,mystat.st_nlink,getpwuid(mystat.st_uid)->pw_name,getgrgid(mystat.st_gid)->gr_name,mystat.st_size,ptm+4,myent ->d_name); } } printf("\n"); return 0 ; } void mode_to_str(mode_t md, char* str) { strcpy(str,"----------"); if(S_ISDIR(md)) { str[0]='d'; } if(md & S_IRUSR) { str[1] ='r'; } if(md & S_IWUSR) { str[2]='w'; } if(md & S_IXUSR) { str[3] = 'x' ; } if(md & S_IRGRP) { str[4] ='r'; } if(md & S_IWGRP) { str[5]='w'; } if(md & S_IXGRP) { str[6] = 'x' ; } if(md & S_IROTH) { str[7] ='r'; } if(md & S_IWOTH) { str[8]='w'; } if(md & S_IXOTH) { str[9] = 'x' ; } } void format(char* p) { while(*p) { p++ ; } while(*p != ':') { p-- ; } *p = '\0'; }
S_ISDIR(mode) |
判断是否是目录 |
最后有一个总结性性的程序
客户端发送文件名 或者目录 到服务器, 服务器读出当前目录或者对应文件的的内容
发送给客户端。使用TCP和创建线程处理请求。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <fcntl.h> #include <pthread.h> #include <dirent.h> #define IP "192.168.1.61" #define PORT 8888 int fd_sever,fd_client; void *read_func(void *arg); int main(int argc,char *argv[]) { pthread_t tid; signal(13,SIG_IGN); //socket当作文件 fd_sever=socket(AF_INET,SOCK_STREAM,0);//协议不用管,会自己判断ipv4, if(fd_sever==-1) { perror("socket failed!\n"); exit(-1); } //绑定,端口号IP绑定到socket struct sockaddr_in sever_addr; memset(&sever_addr,0,sizeof(sever_addr)); sever_addr.sin_family=AF_INET; sever_addr.sin_port=htons(PORT);//小端转大端 sever_addr.sin_addr.s_addr=inet_addr(IP);//网络字节序 if(bind(fd_sever,(const struct sockaddr *)&sever_addr,sizeof(sever_addr))==-1) { perror("bind\n"); close(fd_sever); exit(-1); } //监听,设置为监听状态,第二个参数为监听人数,来请求放入监听队列,可放五人 if(listen(fd_sever,5)==-1) { perror("listen\n"); close(fd_sever); exit(-1); } //从监听队列获取请求,返回客户端描素福,与对面联系。取出连接 struct sockaddr_in client_addr; int len=sizeof(client_addr); fd_client=accept(fd_sever,(struct sockaddr *)&client_addr,&len); //recv ,对面先发则先收read也可以,sever只负责取连接, char buf[1024]=""; // int recv_n=recv(fd_client,buf,1024,0); while(recv(fd_client,buf,1024,0)>0) { printf("%s\n",buf); pthread_create(&tid,NULL,read_func,(void *)buf); } printf("ok\n"); //printf("recv from IP :%s\n Msg:%s\nLen:%d\n",inet_ntoa(client_addr.sin_addr),recv_buf,recv_n); //int send_n=send(fd_client,recv_buf,recv_n,0); //printf("send from IP :%s:%d\nMsg:%s\nLen:%d\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),recv_buf,send_n); close(fd_sever); close(fd_client); return 0; } void *read_func(void *arg) { char *p=(char *)arg; printf("arg:%s\n",(char *)arg); pthread_detach(pthread_self());//系统回收资源 int pid,fd_write,fd_path,n,index=0; //char cpid[1024]=""; char path[1024]=""; //char fifo_write[1024]=""; char buf[1024]; DIR *Pdir; struct dirent *myent; //printf("p = %s\n",p); sscanf(p,"%s",path); //pid=atoi(cpid); //index=strlen(cpid)+1; //printf("index=%d\n",index); //printf("pid = %d\n",pid); //sscanf(p+index,"%s",path);//文件 printf("path:%s\n",path); //sprintf(fifo_write,"%d_read.fifo",pid);//客户端读管道,系统成为写管道 //fd_write=open(fifo_write,O_WRONLY); n=chdir(path); if(n==0)//目录 { printf("n=%d\n",n); Pdir=opendir(path); while((myent=readdir(Pdir))!=NULL) { printf("pname=%s\n",myent->d_name); fd_path=open(myent->d_name,O_RDONLY); while(memset(buf,0,1024),read(fd_path,buf,1024)>0) { write(fd_client,buf,strlen(buf)); } } } else//文件 { fd_path=open(path,O_RDONLY); while(memset(buf,0,1024),read(fd_path,buf,1024)>0) { // printf("fd_path:%s\n",buf); write(fd_client,buf,strlen(buf)); } } close(fd_path); }
客户端主要是与服务器建立连接
发送请求
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #define SEVER_PORT 8888 #define SEVER_IP "192.168.1.61" int main(int argc,char *argv[]) { int fd_client; struct sockaddr_in sever_addr; memset(&sever_addr,0,sizeof(struct sockaddr_in)); fd_client=socket(AF_INET,SOCK_STREAM,0); if(fd_client==-1) { perror("socket!\n"); exit(-1); } sever_addr.sin_family=AF_INET; sever_addr.sin_port=htons(SEVER_PORT); sever_addr.sin_addr.s_addr=inet_addr(SEVER_IP); connect(fd_client,(struct sockaddr*)&sever_addr,sizeof(sever_addr)); printf("connecting!\n"); char *p="/home/study/0701"; send(fd_client,p,strlen(p),0); char buf[1024]=""; while(memset(buf,0,1024),read(fd_client,buf,1024)) { //printf("%s\n",buf); write(1,buf,strlen(buf)); fflush(stdout); // send(fd_client,buf,strlen(buf),0); } //int recv_n=recv(fd_client,buf,1024,0); //printf("recv from ip:port %s:%d\nMsg:%s\nlen=%d\n",inet_ntoa(sever_addr.sin_addr),ntohs(sever_addr.sin_port),buf,recv_n); close(fd_client); return 0; }
总结文件操作函数-目录(三)-C语言