Linux下IO编程(一)

  • Linux下IO编程
    • 文件IO
      • open函数——打开or创建一个文件
      • write函数
      • read函数
      • lseek函数

Linux下IO编程

文件IO

open函数——打开or创建一个文件

#include <fcntl.h> //open函数在此头文件中声明
int open(const char *pathname, int flags, mode_t mode)

参数意义如下:

  • pathname——文件路径
  • flags ——打开文件的方式
  • mode——创建文件的权限(可省略)

flags的内容如下:

flags 功能
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读写打开
O_CREAT 若路径中的文件不存在则自动建立该文件
O_APPEND 读写文件从文件尾部开始移动,所写入
O_TRUNC 打开文件,会把已经存在的内容删除
O_EXCL O_CREAT |O_EXCL指令会去检查文件是否存在,文件若不存在则建立,否则返回-1

mode的表示方法1:

mode 功能
S_IRUSR 所有者拥有读权限
S_IWUSR 所有者拥有写权限
S_IXUSR 所有者拥有执行权限
S_IRGRP 群组拥有读权限
S_IWGRP 群组拥有写权限
S_IXGRP 群组拥有执行权限
S_IROTH 其他用户拥有读权限

mode的表示方法2:——可以由3位数字组成(umask)

数值 第一位 第二位 第三位
4(读) 所有者 群组 其他用户
2(写)
1(执行)

函数返回值

函数的返回值是文件描述符,如果打开文件成功返回一个正整数,否则返回-1。文件描述符,是一个非负的整数,相当于文件的ID号。

举例:通过open函数实现touch功能

#include <stdio.h>                         // 提供open()函数
#include <fcntl.h>
#include <unistd.h>                        // 提供close()函数
int main(int argc,char* argv[])
{int fd;fd =open(argv[1],O_CREAT | O_RDWR,0777);if(fd<0){printf("create file %s is failed\n",argv[1]);return -1;}else{printf("create file %s is sucess,fd is %d\n",argv[1],fd);}close(fd);return 0;
}

write函数

#include <unistd.h>
ssize_t write (int fd, const void * buf, size_t count);

参数

  • fd——文件描述符
  • buf——写入内容
  • cout——向文件中写多少(字节)

函数返回值:返回实际写入的字节数。

举例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char* argv[])
{int fd;int wr_ret;char buf[]="hello linux";fd=open("./a.c",O_TRUNC |O_RDWR);if(fd<0){printf("open file is failed");return -1;}printf("open file is success ,fd is %d\n",fd);wr_ret=write(fd,buf,sizeof(buf));printf("the wr_ret is %d\n",wr_ret);          //12个字节 加上“\0”close(fd);return 0;
}

read函数

#include <unistd.h>
ssize_t read(int fd, void * buf, size_t count);

函数说明:

read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。

返回值:返回值为实际读取到的字节数

注意:

  1. 先写再读会涉及一个指针读写位置指针,在写完的指针位置进行读会读不到内容,如下举例
  2. read时fd中的数据如果小于要读取的数据,就会引起阻塞,详见:https://blog.csdn.net/hhhlizhao/article/details/71552588

举例:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char* argv[])
{int fd;int wr_ret,rd_ret;char buf[]="hello linux";char rd_buf[]={0};fd=open("./a.c",O_TRUNC |O_RDWR);if(fd<0){printf("open file is failed");return -1;}printf("open file is success ,fd is %d\n",fd);wr_ret=write(fd,buf,sizeof(buf));printf("the wr_ret is %d\n",wr_ret);//readrd_ret=read(fd,rd_buf,128);printf("the rd_ret is %d,the rd_buf is %s\n",rd_ret,rd_buf);close(fd);return 0;
}
//以上输出为
open file is success ,fd is 3
the wr_ret is 12
the rd_ret is 0,the rd_buf is  //发现读不到

lseek函数

#include <sys/types.h>
#include <unistd.h>
off_t  lseek(int fd, off_t offset, int whence)

函数作用:

用于移动文件读写指针,因此还有以下两种作用:

  • 扩展文件;
  • 获取文件大小;lseek(fd,0,SEEK_END)

参数

  • fd——文件描述符
  • offset——相对基准的偏移量,字节为单位,为正则向文件末尾移动(向前移),为负数则向文件头部(向后移)
  • whence——当前的基准

whence主要有3个标志:

whence 说明
SEEK_SET 从文件头部开始偏移offset个字节
SEEK_CUR 从文件当前读写的指针位置开始,增加offset个字节的偏移量
SEEK_END 从文件结尾开始,文件偏移量设置为文件的大小加上偏移量字节

返回值:成功,返回从文件开头到当前结束位置的偏移量(1字节为单位);失败返回-1。

举例1:对上个例子应用lseek()将读写指针移到开头,来实现先写再读

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char* argv[])
{int fd;int wr_ret,rd_ret;char buf[]="hello linux";char rd_buf[]={0};fd=open("./a.c",O_TRUNC |O_RDWR);if(fd<0){printf("open file is failed");return -1;}printf("open file is success ,fd is %d\n",fd);wr_ret=write(fd,buf,sizeof(buf));printf("the wr_ret is %d\n",wr_ret);//start read lseek(fd,0,SEEK_SET);   //<========================================rd_ret=read(fd,rd_buf,128);printf("the rd_ret is %d,the rd_buf is %s\n",rd_ret,rd_buf);close(fd);return 0;
}
//经过lseek()函数调整读写指针位置后
open file is success ,fd is 3
the wr_ret is 12
the rd_ret is 12,the rd_buf is hello linux

举例2:综合应用——使用以上所学完成类似cp操作

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char* argv[])
{int rd_fd,wr_fd;int rd_ret;int wr_ret;char read_buf[128]={0};if(argc<3){printf("are you kiding me? ");return -1;}rd_fd=open(argv[1],O_RDONLY);if(rd_fd<0){printf("open the src file:%s  is failed\n",argv[1]);return -2;}printf("open the %s is sucessful\n",argv[1]);wr_fd=open(argv[2],O_WRONLY);if(wr_fd<0){printf("open the des file:%s is failed\n",argv[2]);return -3;}printf("open the %s is sucessful\n",argv[2]);while(1){rd_ret=read(rd_fd,read_buf,128);         //read时有读写指针wr_ret=write(wr_fd,read_buf,rd_ret);     //所以此处一次读不完但是也能连续if(rd_ret<128){break;}memset(read_buf,0,128);}close(wr_fd);close(rd_fd);return 0;}

注:

  1. 从文件向buf中read时,因为文件有读写指针,并且一次循环read完一个buf马上进行write,所以最终得到的内容是连续的。但是要注意write函数,write()函数从buf写数据到fd中时,若buf中数据无法一次性读完,那么第二次读buf中数据时,其读位置指针(也就是第二个参数buf)不会自动移动,需要程序员来控制,而不是简单的将buf首地址填入第二参数即可。

    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    int main(int argc,char* argv[])
    {int wr_fd;int wr_ret;char buf[]="hello linux";wr_fd=open(argv[1],O_CREAT |O_RDWR,0666);if(wr_fd<0){printf("open the file is failed");return -1;}wr_ret=write(wr_fd,buf,2); wr_ret=write(wr_fd,buf,2);//写两次结果可能为“hehe” or "hell"close(wr_fd);return 0;
    }
    
    //编译后执行
    ./test test.c
    得到test.c文件中内容为“hehe”
    

    可按如下格式实现buf读位置移动:write(fp, p1+len, (strlen(p1)-len))。 这样write第二次循环时便会从p1+len处写数据到fp, 之后的也一样。由此类推,直至(strlen(p1)-len)变为0。

    int main()
    {char *p1 = "This is a c test code";volatile int len = 0;int fp = open("/home/test.txt", O_RDWR|O_CREAT);for(;;){int n;n=write(fp, p1+len, (strlen(p1)-len);if(n== 0)   {                                                 printf("n = %d \n", n);break;}len+=n;       }return 0;
    
  2. 以上例子还未用到lseek()函数,因为以上函数是直接cp复制一个编辑好的文件,而不是复制通过write函数写出的文件。

Linux下IO编程(一)相关推荐

  1. linux v4l2 反操作,Linux下V4L2编程小结--吴老师

    作者:武汉华嵌-嵌入式培训中心  吴老师 Linux下V4L2编程小结 一.设置采集方式,格式 常用命令标志 打开视频设备后,可以设置该视频设备的属性,例如裁剪.缩放等.这一步是可选的.在Linux编 ...

  2. Linux下Socket编程

    Linux下Socket编程    网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符.Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的S ...

  3. Linux下高性能网络编程中的几个TCP/IP选项

    Linux下高性能网络编程中的几个TCP/IP选项 转自:http://blog.chinaunix.net/u/12592/showart.php?id=2064847 最近在新的平台上测试程序,以 ...

  4. linux下多进程编程简介

    两年前的文章,拿过来充充门面. ------------------------ linux下多进程编程简介 ( 作者:mikespook | 发布日期:2002-12-8 | 浏览次数:272 ) ...

  5. [zz]Linux 下 socket 编程示例

    本示例为 Client/Server 结构,通过代码演示 Client 如何建立连接,并向远程端发送数据:Server 端如何侦听系统连接请求,接收请求并建立连接,进而获取客户端发来的数据.代码虽短, ...

  6. Linux下网络编程

    Linux下网络编程初步 Linux以其源代码公开闻名于世,并以其稳定性和可靠性雄霸操作系统领域,在网络应用技术方面使用得更加广泛.很久以来它就是Windows的重要对手之一.随着网络时代的来临,Li ...

  7. linux下 C编程改变输出字体颜色

    linux下 C编程改变输出字体颜色 分类: Linux基础编程 Linux操作系统 2012-09-19 10:53 1409人阅读 评论(0) 收藏 举报 linux编程c 格式: echo &q ...

  8. linux实验串行端口程序设计,Linux下串口编程心得(转)

    最近一段时间,需要完成项目中关于Linux下使用串口的一个部分,现在开帖记录过程点滴. 项目的要求是这样的,Qt应用程序主要完成数据采集和发送功能,一开始在google中海搜关键字"Qt串口 ...

  9. linux下Bash编程until语句及格式化硬盘分区等编写脚本(十)

    linux下Bash编程until语句及格式化硬盘分区等编写脚本(十) 1.循环语句结构总结 1.1.while语句当条件满足时,进入循环语句 while 条件; do 语句 done 1.2.unt ...

最新文章

  1. git reset revert 回退回滚取消提交返回上一版本
  2. android listview 去掉水波纹效果_CocosCreator之分层管理的ListView
  3. Android学习——ListView的缓存机制
  4. [Swift]LeetCode46. 全排列 | Permutations
  5. DPM 2012 R2恢复Exchange 2013单用户邮箱
  6. cygwin下各盘挂载点
  7. java微信上传本地视频教程_java微信开发之上传下载多媒体文件,java上传下载_PHP教程...
  8. 【脚本开发】:性能测试-Java虚拟用户实现下载脚本
  9. bzoj 2795 [Poi2012]A Horrible Poem hash+线性筛
  10. 非关系型数据库和关系型数据库区别(转载)
  11. c++/cli 之数据库操作
  12. Typora下载安装详细步骤
  13. 信息安全工程师考试科目
  14. word文件做一半未响应_word编辑一半未响应怎么办
  15. VUE时间戳和时间相互转换,使用UI库为Ant Design of Vue
  16. tplink查看上网记录_Tplink路由器PPPOE拨号不能上网日志查看原因
  17. kali2.0 安装 网易云音乐(无法打开解决方法)和为知笔记
  18. 最成功的失败学——《创游记:游戏团队创业成长之路》
  19. Quorum NWR
  20. 安装pandas成功但import不成功的解决办法

热门文章

  1. iPhone出现绿屏问题怎么修复?可以尝试这些解决方案
  2. [生存志] 第83节 墨子开宗称显学
  3. 吴恩达Deep learning笔记(一)
  4. mysql将多行结果合并
  5. puzzle(0112)不规则数独、变种数独
  6. mysql如何数据恢复
  7. 【2020 ACM Fellow 华人学者】 陶宇飞 香港中文大学
  8. matlab距离判别分析的应用
  9. ERROR:ORA-01031:insufficient privileges完美解决方法
  10. TensorFlow 、Caffe等9大人工智能框架对比介绍