Linux 系统调用IO口,利用光标偏移实现文件复制
用系统调用IO函数实现从一个文件读取最后2KB数据并复制到另一个文件中,源文件以只读方式打开,目标文件以只写的方式打开,若目标文件不存在,可以创建并设置初始值为0664,写出相应代码,要对出错情况有一定的处理,并能够让用户自行输入要复制的文件名。
IO口即指Input和Outpot,常用的IO函数open() , close() , read() , write() ,lseek()。本节也围绕以上函数完成。
题目分析:
本质:从一个文件读取,然后写到另一个文件里。
添加形容:
源文件(要读取的文件),目标文件(要写入的文件)
源文件以只读方式打开:from_writed=open(argv[1],O_RDONLY);
目标文件以只写方式打开:to_readed=open(argv[2],O_WRONLY);
若目标文件不存在可以创建并设置初始值为0664:to_readed=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664);
命令简介:
O_RDONLY --以只读命令打开文件
O_WRONLY--以只写命令打开文件
O_WRONLY--以读写命令打开文件
O_CREAT--若文件不存在则创建
O_TRUNC--若文件存在则清除原有数据
最后一个参数mode 是文件权限,0代表没有权限,1代表可执行权限,2代表可写权限,4代表可读权限,将其相加可得0~7的八进制数。
0664表示的是 文件所有者可读可写,和文件所有者同组用户可读可写,其他用户可读。
对出错情况有一定的处理:
if(xx<0)
{
printf("can't open %s",argv[x]);
return-1
}
或者
if(xx<0)
{
perror("xx");
}
(要使用perror(),前提引用库函数 #include<error.h>
让用户自行输入要复制的文件名:
这里主函数里写入参数
int main(int argc, char *argv[])
argc用来传参,此篇argc一共有三个参数,除了程序名还有两个,分别是源文件和目标文件(“要被复制的文件”和“要复制到的文件”),基于此实现用户自行输入要复制的文件名。
读取源文件最后2kb的数据:
用lseek()函数实现
int len; len=lseek(from_writed,-70,SEEK_END);
题目要求是最后2kb,但是2048太大了,我写的文件比较小,我就偏移个最后70,刚好是我文件最后一句话。
大家自己看,想偏多少都行。
函数原型
off_t lseek(int fd , off_t offset, int whence)
先来说一下这个off_t类型吧,它用于指示文件的偏移量。你可以就简单的理解为这是一个64位的整形数,相当于long long int,其定义在unistd.h头文件中可以查看。
参数:fd //文件描述符,可以通过open函数得到,通过这个fd可以操作某个文件
参数: offset //文件偏移量,是一个整形数
参数:whence //偏移类型,下列三个值中选一个。offset:
offset > 0 向后偏移
offset < 0 向前偏移
whence :
SEEK_SET:从文件头开始偏移
SEEK_CUR:从当前位置开始偏移
SEEK_END:从文件尾开始偏移
在使用这个函数之前,我们需要往C/C++文件中导入这些头文件:
#include <sys/types.h>
#include <unistd.h>
到此题目就分析完了。
写代码
先创个源文件
vi LLL
IO实现文件全部复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <error.h>
int main(int argc, char *argv[])
{
if(argc != 3)
{
printf("Input error\n");
exit(1);
}
int fp_from = open(argv[1], O_RDONLY);//只读
if(fp_from==-1)
{
printf("open %s error\n",argv[1]);
exit(2);
}
int fp_to = open(argv[2], O_WRONLY | O_CREAT, 0644);//读写,不存在则创建
if(fp_to==-1)
{
printf("open %s error\n",argv[2]);
exit(3);
}
int buf[1024] = {0};
ssize_t ret;
while(1)
{
ret = read(fp_from,buf,sizeof(buf) - 1);//从源文件读
if(ret == -1)
{
perror("read");
}
else if(ret == 0)
{
printf("拷贝完毕\n");
break;
}
ret == write(fp_to,buf,ret); //向目标文件写
if(ret == -1)
{
perror("write");
}
}
close(fp_from);
close(fp_to);
return 0;
}
运行结果:
利用光标偏移,IO实现文件部分复制
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(int argc,char **argv)
{ int from_writed; //源文件
int to_readed; //目标文件
int l_writed; //写入长度
int l_readed; //读取长度
int buf[2048];
int len; //偏移长度
if(argc != 3)
{
printf("Input error\n");
return -1;
}
from_writed=open(argv[1],O_RDONLY);//以只读方式打开源文件
if(from_writed<=0)
{
printf("can't oppen %s\n",argv[1]);
return -1;
}
to_readed=open(argv[2],O_WRONLY);//以只写方式打开目标文件
if(to_readed<=0) //如果文件不存在
{
to_readed=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664);
//读写方式|不存在则创建|存在则清除数据,权限0664
if(to_readed<=0)
{
printf("can't open %s\n",argv[2]);
return -1;
}
}
while(1)
{
// off_t len;
len=lseek(from_writed,-70,SEEK_END); //移动光标至文件末尾前70个数据
if(len>0)
{
printf("current off_t : %d\n",len);输出当前光标位置所在
}
l_readed=read(from_writed,buf,2048); //从源文件读取
if(l_readed<0)
{
printf("can't read from %s\n",argv[1]);
return -1;
}
if(l_readed>0)
{
l_writed=write(to_readed,buf,l_readed);//写入到目标文件
if(l_writed>0)
{
printf("拷贝完毕\n");
break;
}
if(l_writed<0)
{
printf("can't write to %s\n",argv[2]);
return -1;
}
}
else
break;
}
close(from_writed);
close(to_readed);
return 0;
}
还利用上面那个LLL文件
运行:
查看:
刚好偏移最后一句话。