任务一
使用Linux系统调用编写一个完成文件拷贝的C程序。
相关代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<dirent.h>
#define SIZE 1024 // 1024字节
/*文件是否存在*/
int is_Exist(char *file)
{
if(access(file,F_OK) == -1)
{
perror("access");
return -1;
}
return 0;
}
/*文件是否可读*/
int is_Readable(char *file)
{
if(access(file,R_OK)==-1)
{
printf("No read permission for '%s' file\n",file);
return -1;
}
return 0;
}
/*文件是否为目录文件*/
int is_Dir(char *file)
{
/*获取文件状态信息*/
struct stat st;
if(stat(file,&st)==-1){perror("stat");exit(3);}
/*判断是否是目录文件*/
if(S_ISDIR(st.st_mode)){return 0;}
return -1;
}
/*文件到文件拷贝*/
void copy_file(char *src_file,char *dst_file)
{
char choice; // 用户意愿
int src_fd,dst_fd; // 记录源文件描述符,目标文件描述符
int rd,wr; // 实际读的字节数,写的字节数
int buf[SIZE]; // 存放读写的内容
struct stat st; // 记录目标文件状态信息
int ret=-1; // 记录获取目标文件状态信息是否成功
int flag=1;
/*打开源文件*/
src_fd=open(src_file,O_RDONLY);
if(src_fd==-1){perror("open");exit(4);}
/*打开目标文件,若不存在,则根据用户意愿创建目标文件*/
if(access(dst_file,F_OK) == -1)
{
perror("access");
while(flag)
{
printf("Is create '%s' file ?(Y/N):",dst_file);
scanf("%c",&choice);
switch(choice)
{
case 'N':
case 'n':
exit(0);
case 'Y':
case 'y':
umask(0000); // 临时改变umask的值
dst_fd=open(dst_file,O_RDWR|O_CREAT,0666);
if(dst_fd==-1){perror("open");exit(5);}
printf("Create successfully !\n");
flag=0;
break;
default:
printf("Input error !\n");
break;
}
}
}else{ // 目标文件存在
ret=stat(dst_file,&st); // 获取目标文件状态信息
if(ret==-1)
{
perror("stat");
exit(6);
}
/*目标文件不为空,根据用户意愿覆盖文件*/
if(st.st_size>0)
{
char choice; // 用户意愿
int flag=1;
while(flag)
{
printf("Do you want to overwrite '%s' file ?(Y/N):",dst_file);
scanf("%c",&choice);
switch(choice)
{
case 'N':
case 'n':
exit(0);
case 'Y':
case 'y':
dst_fd=open(dst_file,O_RDWR|O_TRUNC);
if(dst_fd==-1)
{
perror("open");
exit(8);
}
flag=0;
break;
default:
printf("Input error !\n");
break;
}
}
}else // 目标文件为空
{
dst_fd=open(dst_file,O_RDWR);
if(dst_fd==-1){perror("open");exit(9);}
}
}
/*拷贝源文件内容到目标文件中*/
while(1)
{
/*要求从源文件中每次读出SZIE字节内容*/
rd=read(src_fd,buf,SIZE);
if(rd==-1)
{
printf("Read failure about '%s' file\n",src_file);
exit(8);
}
/*实际读出字节数为0,表明拷贝完成*/
if(rd==0){printf("Copy successfully !\n");break;}
/*要求每次写入rd字节内容到目标文件*/
wr=write(dst_fd,buf,rd);
if(wr==-1)
{
printf("Write failed about '%s' file\n",dst_file);
exit(9);
}
}
/*完成相关文件操作后,关闭文件*/
close(src_fd);
close(dst_fd);
exit(0);
}
/*字符串连接*/
char* str_contact(char* src_file,char* dst_dir)
{
char* string;
/*src_file的长度+dst_dir的长度+\0*/
string=(char*)malloc(strlen(src_file)+strlen(dst_dir)+1);
/*对开辟内存空间失败进行处理*/
if (string == NULL ) { printf("Out of memory !\n"); exit(1); }
memset(string, 0, strlen(src_file)+strlen(dst_dir)+1); // 初始化string
strcat(string,src_file);
strcat(string,dst_dir);//字符串拼接
return string;
}
int main(int argc,char *argv[])
{
/*程序输入的参数是否正确*/
if(argc < 3)
{
printf("Usage:./copy_file src_file1 src_file2 ... dst_file\n");
exit(1);
}
if(argc==3)
{
/*文件到文件的拷贝*/
if(is_Exist(argv[1])==-1){exit(2);} // 源文件存在
if(is_Dir(argv[1])==0){exit(3);} // 源文件非目录文件
if(is_Readable(argv[1])==-1){exit(4);} // 源文件可读
if(is_Exist(argv[2])==-1) // 目标文件不存在
{
copy_file(argv[1],argv[2]); // 拷贝文件
}else{ // 目标文件存在
if(is_Dir(argv[1])==-1) // 目标文件非目录文件
{
copy_file(argv[1],argv[2]); // 拷贝文件(文件->文件)
}else{ // 目标文件是目录文件
/*文件到目录的拷贝*/
argv[2]=str_contact(argv[1],"/");
argv[2]=str_contact(argv[1],argv[2]); // 拼成生成文件路径
copy_file(argv[1],argv[2]); // 拷贝文件(文件->目录下)
}
}
}else{
/*多个文件拷贝到目标目录下*/
for(int i=1;i<argc-1;i++)
{
if(is_Exist(argv[i])==-1){exit(2);} // 源文件存在
if(is_Dir(argv[i])==0){exit(3);} // 源文件非目录文件
if(is_Readable(argv[i])==-1){exit(4);} // 源文件可读
}
/*目标文件存在且为目录文件*/
char *temp=argv[argc-1];
if(is_Exist(argv[argc-1])==0&&is_Dir(argv[argc-1])==0)
{
for(int i=1;i<argc-1;i++)
{
/*文件到目录的拷贝*/
argv[argc-1]=str_contact(argv[i],argv[argc-1]); // 拼成生成文件路径
copy_file(argv[i],argv[argc-1]); // 拷贝文件(文件->目录下)
}
}else{
printf("'%s' ERROR !\n",temp);
exit(5);
}
}
exit(0);
}
运行结果
任务二
编写C程序完成:创建一个新文件,输入一段数据,然后随机移动指针接着插入一段数据。完成后,查看该文件的大小和内容。
相关代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#define SIZE 4 // 4字节
/*接收用户输入的字符/字符串,按回车键结束输入*/
char* inputStr()
{
char* string; // 用户输入的内容
char ch; // 用户输入的单个字符
int i = 0; // 用户输入的字符数量
int count = 0; // 字符指针string扩充空间的次数
string = (char*)malloc(sizeof(char) * SIZE + 1); // 开辟存放SIZE+1字节的内存空间
/*对开辟内存空间失败进行处理*/
if (string == NULL ) { printf("Out of memory !\n"); exit(1); }
memset(string, 0, sizeof(char) * SIZE + 1); // 初始化string
printf("Please input content:"); // 提示用户输入
/*接收用户输入*/
while ((ch = getchar()) != '\n')
{
string[i] = ch;
i++;
/*若开辟的内存空间已满,则动态扩充空间大小*/
if (i % SIZE == 0)
{
string = (char*)realloc(string, sizeof(char) * SIZE * (i / SIZE + 1) + 1);
count++;
/*对开辟内存空间失败进行处理*/
if (string == NULL) { printf("Out of memory !\n"); exit(1); }
memset(string+SIZE*count, 0, sizeof(char) * SIZE + 1); //初始化新增部分空间
}
}
printf("Input successfully !\n");
return string;
}
int main(int argc,char *argv[])
{
char *str1; // 用户开始写入的数据
char *str2; // 用户要插入的数据
char *buf; // 存放读取的文件内容
int size=0; // 记录文件大小
int insert; // 用户选择插入位置
int fd=-1; // 记录目标文件描述符
int wr=-1; // 实际写入的字节数
int rd=-1; // 实际读取的字节数
int ret=-1; // 记录文件偏移量
/*程序输入的参数是否正确*/
if(argc !=2)
{
printf("Usage:./create_file new_file\n");
exit(2);
}
/*目标文件是否存在*/
if(access(argv[1],F_OK) !=-1)
{
printf("The '%s' file already exists !\n",argv[1]);
exit(3);
}
/*创建目标文件并赋予ugo=644*/
fd=open(argv[1],O_RDWR|O_CREAT,0644);
if(fd ==-1){perror("open");exit(4);}
/*接收用户开始输入的数据*/
str1=inputStr();
printf("%s\n", str1);
/*接收用户要插入的数据*/
str2=inputStr();
printf("%s\n", str2);
/*将用户开始输入的数据写入文件*/
wr=write(fd,str1,strlen(str1));
if(wr==-1){perror("write");exit(5);}
/*获取插入前文件字节数*/
ret=lseek(fd,0,SEEK_CUR);
if(ret==-1){perror("sleek");exit(6);}
size=ret;
/*随机生成插入位置*/
printf("Before insrting,the file size is %d bytes !\n",size);
insert=rand()%(size+10)+1; // 1到size+10之间
printf("The postion of the insertion is %d !\n",insert);
/*根据随机生成的插入位置插入相关内容*/
{
/*在文件尾部或更后面插入内容*/
if(insert>size)
{
/*将指针移到插入位置*/
ret=lseek(fd,insert-1,SEEK_SET);
if(ret==-1){perror("sleek");exit(6);}
/*将插入数据写入文件*/
wr=write(fd,str2,strlen(str2));
if(wr==-1){perror("sleek");exit(5);}
printf("Write succeeded !\n");
}else{
/*将指针移到插入位置*/
ret=lseek(fd,insert-1,SEEK_SET);
if(ret==-1){perror("sleek");exit(6);}
// 开辟存放size-insert+2字节的内存空间
buf=(char *)malloc(sizeof(char)*(size-insert+1)+1);
/*对开辟内存空间失败进行处理*/
if(buf==NULL){printf("Out of memory !\n");exit(1);}
memset(buf, 0, sizeof(char)*(size-insert+1)+1); // 初始化buf
/*读取用户插入位置后面的字符*/
rd=read(fd,buf,(size-insert+1));
if(rd==-1){perror("read");exit(7);}
/*将指针重新移到插入位置*/
ret=lseek(fd,insert-1,SEEK_SET);
if(ret==-1){perror("sleek");exit(6);}
/*将插入数据写入文件*/
wr=write(fd,str2,strlen(str2));
if(wr==-1){perror("sleek");exit(5);}
/*将需移动的内容重新写入文件*/
wr=write(fd,buf,rd);
if(wr==-1){perror("sleek");exit(5);}
printf("Write succeeded !\n");
}
}
/*获取插入前文件字节数*/
ret=lseek(fd,0,SEEK_CUR);
if(ret==-1){perror("sleek");exit(6);}
size=ret;
printf("After insrting,the file size is %d bytes !\n",size);
close(fd); // 关闭文件
exit(0);
}
运行结果