前言
前一阶段学习了文件IO函数,现在打算写一个综合一点的程序,实现这样的功能:
从给定的目录下,下载某个文件到当前目录。
Linux系统的一大特点就是,支持多用户同时登陆,那么就会经常出现这样的场景:某个用户需要从共享文件夹里下载点东西。我们可以试着写一份代码实现上述功能。
我们代码的基本框架是这样的:
- 用户输入一个目录,程序负责打开该目录
- 列出该目录下所有文件
- 用户输入需要下载的文件名
- 打开用户输入的文件
- 将文件中的内容拷贝到当前目录新建的文件里
- 关闭文件和目录
如何打开一个目录
其实目录的打开操作和之前学的文件打开很相似,常用到的函数有:
DIR *opendir(const char *name); //打开目录
struct dirent *readdir(DIR *dirp); //读取目录内文件,以结构体形式返回一个文件或目录
void rewinddir(DIR *dirp); //将目录指针设置到起始位置
void seekdir(DIR *dirp, long loc); //设置目录指针位置
int closedir(DIR *dirp); //关闭目录
这里需要注意一下:目录打开后,里面的子目录和文件,都是用链表连接到一起的,readdir()函数可以从某一节链表读取到一个数据段,并通过结构体:dirent返回,该结构体包含:
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
调用readdir()函数后,目录指针就指向下一个链表节点。再次调用readdir()函数,就可以直接读取到下一个子目录或文件。
程序实现
#include <stdio.h>
#include <string.h>
#include <dirent.h>
int main(void)
{
char src_dir[128]={0};
char src_file[128]={0};
DIR *dp;
FILE *src_fp,*des_fp;
struct dirent *dir;
char buffer[128]={0};
int count=0;
printf("please input src dir.\n"); //获取下载目录
scanf("%s",src_dir);
dp = opendir(src_dir); //尝试打开下载目录
if(dp==NULL){
printf("dir open failed.\n");
return -1;
}
printf("open dir sucess.\n");
while(1){ //打印该目录下所有文件
dir = readdir(dp);
if(dir==NULL){
printf("end of dir.\n");
break;
}else{
printf("inod is %ld,dir name is %s.\n",dir->d_ino,dir->d_name);
}
}
printf("please input the file need download.\n"); //获取需要下载的文件名
scanf("%s",src_file);
src_fp = fopen(strcat(src_dir,src_file) ,"r"); //打开源文件
if(src_fp==NULL){
printf("src file open failed.\n");
return -2;
}
printf("open src file sucess.\n");
des_fp = fopen("./downld" ,"w"); //打开目标文件
if(des_fp==NULL){
printf("des file open failed.\n");
return -2;
}
printf("open des file sucess.\n");
while(1){ //开始文件拷贝
count = fread(buffer,sizeof(char),sizeof(buffer),src_fp);
if(count<128){
printf("download complete.\n");
break;
}
fwrite(buffer,sizeof(char),count,des_fp);
}
fwrite(buffer,sizeof(char),count,des_fp);
fclose(src_fp); //关闭文件,以及目录
fclose(des_fp);
closedir(dp);
return 0;
}
程序执行结构:
我们打开/mnt/目录,注意这里需要加一个“/”,因为用户输入两次:“/mnt/”和“123.c”,在程序中,我们将两个字符串通过strcat()函数合并,方便fopen()函数找到文件路径,如果不加“/”,最后文件的路径就不对了。
在当前程序目录下,可以看到下载的文件:downld
检查downld文件里的内容是否与123.c中的一致。
至此,该程序编写完成。