• 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表示的是 文件所有者可读可写,和文件所有者同组用户可读可写,其他用户可读。

    对出错情况有一定的处理:

    1. if(xx<0)
    2. {
    3.   printf("can't open %s",argv[x]);
    4. return-1
    5. }
    6. 或者
    7. if(xx<0)
    8. {
    9. perror("xx");
    10. }

    (要使用perror(),前提引用库函数 #include

    让用户自行输入要复制的文件名:

    这里主函数里写入参数

    int main(int argc, char *argv[])

    argc用来传参,此篇argc一共有三个参数,除了程序名还有两个,分别是源文件和目标文件(“要被复制的文件”和“要复制到的文件”),基于此实现用户自行输入要复制的文件名。

     读取源文件最后2kb的数据:

    用lseek()函数实现

    1. int len;
    2. 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
    #include

     到此题目就分析完了。

    写代码

    先创个源文件

    vi LLL

    IO实现文件全部复制

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include <error.h>
    8. int main(int argc, char *argv[])
    9. {
    10. if(argc != 3)
    11. {
    12. printf("Input error\n");
    13. exit(1);
    14. }
    15. int fp_from = open(argv[1], O_RDONLY);//只读
    16. if(fp_from==-1)
    17. {
    18. printf("open %s error\n",argv[1]);
    19. exit(2);
    20. }
    21. int fp_to = open(argv[2], O_WRONLY | O_CREAT, 0644);//读写,不存在则创建
    22. if(fp_to==-1)
    23. {
    24. printf("open %s error\n",argv[2]);
    25. exit(3);
    26. }
    27. int buf[1024] = {0};
    28. ssize_t ret;
    29. while(1)
    30. {
    31. ret = read(fp_from,buf,sizeof(buf) - 1);//从源文件读
    32. if(ret == -1)
    33. {
    34. perror("read");
    35. }
    36. else if(ret == 0)
    37. {
    38. printf("拷贝完毕\n");
    39. break;
    40. }
    41. ret == write(fp_to,buf,ret); //向目标文件写
    42. if(ret == -1)
    43. {
    44. perror("write");
    45. }
    46. }
    47. close(fp_from);
    48. close(fp_to);
    49. return 0;
    50. }

    运行结果:

    利用光标偏移,IO实现文件部分复制

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. int main(int argc,char **argv)
    8. { int from_writed; //源文件
    9. int to_readed; //目标文件
    10. int l_writed; //写入长度
    11. int l_readed; //读取长度
    12. int buf[2048];
    13. int len; //偏移长度
    14. if(argc != 3)
    15. {
    16. printf("Input error\n");
    17. return -1;
    18. }
    19. from_writed=open(argv[1],O_RDONLY);//以只读方式打开源文件
    20. if(from_writed<=0)
    21. {
    22. printf("can't oppen %s\n",argv[1]);
    23. return -1;
    24. }
    25. to_readed=open(argv[2],O_WRONLY);//以只写方式打开目标文件
    26. if(to_readed<=0) //如果文件不存在
    27. {
    28. to_readed=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664);
    29. //读写方式|不存在则创建|存在则清除数据,权限0664
    30. if(to_readed<=0)
    31. {
    32. printf("can't open %s\n",argv[2]);
    33. return -1;
    34. }
    35. }
    36. while(1)
    37. {
    38. // off_t len;
    39. len=lseek(from_writed,-70,SEEK_END); //移动光标至文件末尾前70个数据
    40. if(len>0)
    41. {
    42. printf("current off_t : %d\n",len);输出当前光标位置所在
    43. }
    44. l_readed=read(from_writed,buf,2048); //从源文件读取
    45. if(l_readed<0)
    46. {
    47. printf("can't read from %s\n",argv[1]);
    48. return -1;
    49. }
    50. if(l_readed>0)
    51. {
    52. l_writed=write(to_readed,buf,l_readed);//写入到目标文件
    53. if(l_writed>0)
    54. {
    55. printf("拷贝完毕\n");
    56. break;
    57. }
    58. if(l_writed<0)
    59. {
    60. printf("can't write to %s\n",argv[2]);
    61. return -1;
    62. }
    63. }
    64. else
    65. break;
    66. }
    67. close(from_writed);
    68. close(to_readed);
    69. return 0;
    70. }

    还利用上面那个LLL文件

    运行:

    查看:

    刚好偏移最后一句话。

  • 相关阅读:
    Postgresql源码(115)LLVM JIT运行逻辑分析(上)
    LeetCode--172. 阶乘后的零(C++描述)
    Vue_路由VueRoute
    java毕业设计——基于java+Socket+sqlserver的办公自动化系统设计与实现(毕业论文+程序源码)——办公自动化系统
    LabVIEW 应用程序视窗始终置于顶层
    问题内容总结
    基于智慧城市与储住分离数字家居模式垃圾处理方法
    android的异步任务与handler分析与初步实战
    哈工大李治军老师操作系统笔记【18】:内存使用与分段(Learning OS Concepts By Coding Them !)
    08.24python单元测试之unittest
  • 原文地址:https://blog.csdn.net/bujianzingguang/article/details/134089220