博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Linux-read和write函数

Posted on 2023-03-14 07:03  乔55  阅读(87)  评论(0编辑  收藏  举报

read详解

 int ret = ssize_t read(int fd, void *buf, size_t count);

// ret == -1 :出错,并设置errno
// ret == -1 && errno == EAGAINA:
// 不是read失败,而是以非阻塞方式读设备或网络文件,且文件无数据,直接返回
// 0  :文件读取完毕
// >0 :读取到的字节数

read() attempts to read up to count bytes from fd into the buffer starting at buf,On files that support seeking, the read operation commences at the current file offset, and the file offset is incremented by the number of bytes read. If the current file offset is at or past the end of file, no  bytes  are  read,  and read() returns zero.
// 尝试从fd读满count个字节到一个以buf开始的缓冲区
// 对于支持寻址的文件,读操作从当前文件偏移量开始,且文件偏移量随读取的字节数增长
// 如果当前文件偏移量刚好在文件末尾或超过末尾,将读取到0个字节,且返回0

If  count  is  zero,  read()  may detect the errors described below. In the absence of any errors, or if read() does not check for errors,a read() with a count of 0 returns zero and has no other effects.If count is greater than SSIZE_MAX, the result is unspecified.
// 如果count是0,read可能检测下面所描述的错误。如果没有错误或者没有检测错误,
// count为0的read返回0,且没有其他影响。
// 描述的错误:如果conut大于SSIZE_MAX,则结果是未确定的

On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by  this number. It  is  not  an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal),or because read() was interrupted by a signal.  On error, -1 is returned, and errno is set appropriately.  In this case it is left unspecified whether the file position (if any) changes.
// 成功返回读取的字节数(返回0表示到了文件末尾),且文件指针位置向后移动number个位置。
// 当返回值小于指定的字节数count时并不意味错误,这可能是因为文件当前可读取的字节数
// 小于指定的count字节数:如已经接近文件末尾,或正从管道,终端读取数据或read被信号中断
// 错误时返回-1,并设置合适的errno值。这种情况下无法得知文件偏移位置是否发生变化 

write

ssize_t write(int fd, const void *buf, size_t count);

// 成功:返回定稿的字节数。错误:返回-1并设置errno

用read和write实现mycopy.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUFSIZE 1024

int main(int argc, char** argv)
{
  
  char buf[BUFSIZE];
  int len = 0;  // 记录成功每次read多个字节
  int ret = 0;  // 记录成功每我write多少个字节
  int pos = 0;  // 从buf的哪个位置开始写起入字节
  int sfd = open(argv[1], O_RDONLY);
  if(sfd < 0)
  {
    perror("open() srcFile failed");
    exit(1);
  }
  int dfd = open(argv[2], O_WRONLY | O_CREAT| O_TRUNC, 0666);
  if(dfd < 0)
  {
    close(sfd);
    perror("open() destFile failed");
    exit(1);
  }
  while(1)
  {
    len = read(sfd,buf,BUFSIZE);
    if(len < 0)
    {
      perror("read() failed");
      break;
    }
    if(len == 0)
    {
      break;
    }
    
    // 从dfd文件的开头位置写入数据,用pos来记录第一次写入时的位置
    pos = 0;
    while(len > 0)
    {
      // ret记录实际写了多少个字节进dfd。为什么要记录实际定入的字节数
      // 若已读入100个字节到buf,由于某些原因,实际只写了80个字节
      // 通过ret与pos的结合,可以将未写完的20字节继续写在相应的pos位置
      // 直到将从sfd读到的buf的len个字节全部write到dfd中,才开始下一次read

      ret = write(dfd, buf, len);
      if(ret < 0)
      {
        perror("write() failed");
        close(sfd);
        close(dfd);
        exit(1);
      }
      
      // 成功写入ret个字节后,dfd的文件指针来到ret处位置
      pos += ret;
      len -= ret;
    }
  }
  close(sfd);
  close(dfd);
  return 0;
}