• 封装readn


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <unistd.h>
      5 #include <sys/types.h>
      6 #include <sys/stat.h>
      7 #include <fcntl.h>
      8 #include <sys/wait.h>
      9 #include <errno.h>
     10 #define ERR_EXIT(m) 
     11     do { 
     12         perror(m);
     13         exit(EXIT_FAILURE);
     14     }while(0)
     15 
     16 #define BUFFERSIZE 65536  //缓冲区大小
     17 
     18 typedef struct                  //缓冲区封装为一个结构体  
     19 {
     20     int fd_; //fd
     21     int cnt_; //缓冲区可用的字节数
     22     char *ptr_; //指向缓冲区可用的第一个字节
     23     char buffer_[BUFFERSIZE]; //缓冲区
     24 } rio_t;
     25 
     26 //初始化IO系统
     27 void rio_init(rio_t *rp, int fd)
     28 {
     29     rp->fd_ = fd;
     30     rp->cnt_ = 0;
     31     rp->ptr_ = rp->buffer_;
     32     memset(rp->buffer_, 0, BUFFERSIZE);
     33 }
     34 
     35 //用来替换read
     36 ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
     37 {
     38 
     39     //缓冲区为空时,执行read操作
     40     while(rp->cnt_ <= 0)
     41     {
     42         ssize_t nread = read(rp->fd_, rp->buffer_, BUFFERSIZE);
     43         if(nread == -1)
     44         {
     45             if(errno == EINTR)
     46                 continue;
     47             return -1;  //ERROR
     48         }
     49         else if(nread == 0)
     50             return 0;
     51 
     52         //正常读取
     53         rp->cnt_ = nread;
     54         rp->ptr_ = rp->buffer_; //重置指针
     55     }
     56 
     57     //现有库存和用户要求的数量 取较小者
     58     int cnt = (rp->cnt_ < n) ? rp->cnt_ : n;
     59     memcpy(usrbuf, rp->ptr_, cnt);
     60     rp->ptr_ += cnt;
     61     rp->cnt_ -= cnt;
     62 
     63     return cnt;  //成功读取的字节数
     64 }
     65 
     66 
     67 ssize_t rio_readn(rio_t *rp, void *buf, size_t count)
     68 {
     69     size_t nleft = count;  //剩余的字节数
     70     ssize_t nread; //用作返回值
     71     char *bufp = (char*)buf; //缓冲区的偏移量
     72 
     73     while(nleft > 0)
     74     {
     75         //不再执行read系统调用
     76         nread = rio_read(rp, bufp, nleft);
     77         if(nread == -1)
     78         {
     79             if(errno == EINTR)
     80                 continue;
     81             return -1; // ERROR
     82         }
     83         else if(nread == 0) //EOF
     84             break;
     85 
     86         nleft -= nread;
     87         bufp += nread;
     88     }
     89 
     90     return (count - nleft);
     91 }
     92 
     93 ssize_t rio_readline(rio_t *rp, char *usrbuf, size_t maxlen)
     94 {
     95     int i; //计数
     96     int nread;
     97 
     98     char *bufp = usrbuf;
     99     char c; //暂存字符
    100 
    101     for(i = 0; i < maxlen - 1; ++i)
    102     {
    103         if((nread = rio_read(rp, &c, 1)) == -1)
    104             return -1;
    105         else if(nread == 0) //EOF
    106         {
    107             if(i == 0)
    108                 return 0;
    109             break;
    110         }
    111 
    112         *bufp++ = c; //放入usrbuf
    113         if(c == '
    ') //碰到换行符直接退出循环
    114             break; 
    115     }
    116     *bufp = '';
    117     return i; //返回读取的字节数 
    118 }
    119 
    120 
    121 ssize_t rio_writen(int fd, const void *buf, size_t count)
    122 {
    123     size_t nleft = count;
    124     ssize_t nwrite;
    125     const char *bufp = (const char*)buf;
    126     
    127     while(nleft > 0)
    128     {
    129         nwrite = write(fd, bufp, nleft);
    130         if(nwrite <= 0) // ERROR
    131         {
    132             if(nwrite == -1 && errno == EINTR)
    133                 continue;
    134             return -1;
    135         }
    136 
    137         nleft -= nwrite;
    138         bufp += nwrite;
    139     }
    140     
    141     return count;
    142 }
    143 
    144 
    145 int main(int argc, const char *argv[])
    146 {
    147     int fd = open("test.txt", O_RDONLY);
    148     if(fd == -1)
    149         ERR_EXIT("open test.txt");
    150     rio_t rio;
    151     rio_init(&rio, fd);
    152 
    153     char buf[1024] = {0};
    154     // rio_readn(&rio, buf, 3);
    155     // printf("%s
    ", buf);
    156 
    157     while(rio_readline(&rio, buf, sizeof buf) > 0)
    158     {
    159         printf("%s", buf);
    160     }
    161 
    162     close(fd);
    163 
    164     return 0;
    165 }

    ReadFile.h

     1 #include "ReadFile.h"
     2 
     3 
     4 ReadFile::ReadFile(std::string filename)
     5 : fd_(-1),
     6   filename_(std::move(filename))
     7 {
     8 
     9 }
    10 
    11 ReadFile::~ReadFile()
    12 {
    13     if(fd_ != -1)
    14         close();
    15 }
    16 
    17 bool ReadFile::open()
    18 {
    19     fd_ = ::open(filename_.c_str(), O_RDONLY);
    20     if(fd == -1)
    21         return false;
    22 
    23     buffer_.reset(new RobustIO(fd_));
    24     return true;
    25 }
    26 
    27 void ReadFile::close()
    28 {
    29     ::close(fd_);
    30     fd_ = -1;
    31 }

    ReadFile.cpp

     1 #ifndef READ_FILE_H_
     2 #define READ_FILE_H_
     3 
     4 #include "NonCopyable.h"
     5 #include <string>
     6 
     7 class ReadFile : NonCopyable
     8 {
     9 public:
    10     ReadFile(std::string filename);
    11     ~ReadFile();
    12     bool open();
    13 
    14     ssize_t read(char *usrbuf, size_t count);
    15     ssize_t readn(char *usrbuf, size_t count);
    16     ssize_t readLine(char *usrbuf, size_t maxlen);
    17 
    18     int readInt();   //32 "3211111"
    19     int32_t readInt32();
    20     int64_t readInt64();
    21     string readLine();
    22 
    23     void close();
    24 
    25 private:
    26     int fd_;
    27     std::unique_ptr<RobustIO> buffer_;
    28     const std::string filename_; //文件名
    29 };
    30 
    31 
    32 #endif //READ_FILE_H_

    缓冲区也封装成类

     1 #ifndef ROBUST_IO_H
     2 #define ROBUST_IO_H
     3 
     4 #include "NonCopyable.h"
     5 #include <unistd.h>
     6 
     7 class RobustIO : NonCopyable
     8 {
     9 public:
    10     RobustIO(int fd);
    11     ssize_t readn(char *usrbuf, size_t n);
    12     ssize_t readLine(char *usrbuf, size_t maxlen);
    13     ssize_t writen(int fd, const void *buf, size_t count);
    14 private:
    15     ssize_t read(char *usrbuf, size_t n);
    16 
    17     static const int kBufferSize = 65536;
    18 
    19     int fd_; //fd
    20     int cnt_; //缓冲区可用的字节数
    21     char *ptr_; //指向缓冲区可用的第一个字节
    22     char buffer_[kBufferSize]; //缓冲区
    23 };
    24 
    25 
    26 #endif //ROBUST_IO_H
    #include "RobustIO.h"
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    #include <errno.h>
    #define ERR_EXIT(m) 
        do { 
            perror(m);
            exit(EXIT_FAILURE);
        }while(0)
    
    //const int RobustIO::kBufferSize = 65536;
    
    RobustIO::RobustIO(int fd)
    {
        fd_ = fd;
        cnt_ = 0;
        ptr_ = buffer_;
        ::memset(buffer_, 0, kBufferSize);
    }
    
    ssize_t RobustIO::read(char *usrbuf, size_t n)
    {
        //缓冲区为空时,执行read操作
        while(cnt_ <= 0)
        {
            ssize_t nread = ::read(fd_, buffer_, kBufferSize);
            if(nread == -1)
            {
                if(errno == EINTR)
                    continue;
                return -1;  //ERROR
            }
            else if(nread == 0)
                return 0;
    
            //正常读取
            cnt_ = nread;
            ptr_ = buffer_; //重置指针
        }
    
        //现有库存和用户要求的数量 取较小者
        int cnt = (cnt_ < n) ? cnt_ : n;
        ::memcpy(usrbuf, ptr_, cnt);
        ptr_ += cnt;
        cnt_ -= cnt;
    
        return cnt;  //成功读取的字节数
    }
    
    ssize_t RobustIO::readn(char *usrbuf, size_t count)
    {
        size_t nleft = count;  //剩余的字节数
        ssize_t nread; //用作返回值
        char *bufp = (char*)usrbuf; //缓冲区的偏移量
    
        while(nleft > 0)
        {
            //不再执行read系统调用
            nread = this->read(bufp, nleft);
            if(nread == -1)
            {
                if(errno == EINTR)
                    continue;
                return -1; // ERROR
            }
            else if(nread == 0) //EOF
                break;
    
            nleft -= nread;
            bufp += nread;
        }
    
        return (count - nleft);
    }
    
    ssize_t RobustIO::readLine(char *usrbuf, size_t maxlen)
    {
        int i; //计数
        int nread;
    
        char *bufp = usrbuf;
        char c; //暂存字符
    
        for(i = 0; i < maxlen - 1; ++i)
        {
            if((nread = this->read(&c, 1)) == -1)
                return -1;
            else if(nread == 0) //EOF
            {
                if(i == 0)
                    return 0;
                break;
            }
    
            *bufp++ = c; //放入usrbuf
            if(c == '
    ') //碰到换行符直接退出循环
                break; 
        }
        *bufp = '';
        return i; //返回读取的字节数 
    }
    
    ssize_t RobustIO::writen(int fd, const void *buf, size_t count)
    {
        size_t nleft = count;
        ssize_t nwrite;
        const char *bufp = (const char*)buf;
        
        while(nleft > 0)
        {
            nwrite = write(fd, bufp, nleft);
            if(nwrite <= 0) // ERROR
            {
                if(nwrite == -1 && errno == EINTR)
                    continue;
                return -1;
            }
    
            nleft -= nwrite;
            bufp += nwrite;
        }
        
        return count;
    }
  • 相关阅读:
    JDBC访问数据库的基本步骤是什么?
    Java 为每个原始类型提供了哪些包装类型:
    JDBC访问数据库的基本步骤是什么?
    String 类的常用方法都有那些?
    面向对象三大特性
    三个与取整有关的方法:
    ==和equals方法究竟有什么区别?
    &和&&的区别?
    说一说Servlet的生命周期
    spring框架学习
  • 原文地址:https://www.cnblogs.com/DLzhang/p/4019466.html
Copyright © 2020-2023  润新知