• C C++ POSIX 的一些 IO 操作


    一些 C C++ POSIX 的 IO 操作总结

    • 文件-内存之间
    • 内存-内存之间
    • POSIX 有无缓冲的 IO 操作

    对文件的操作,读文件至内存,从内存写至文件

    // 读文件至内存buf中
    void Fread()
    {
            char buf[BUFSIZE];
            size_t flen = 0;
            FILE *fp = fopen("./foo", "r+");
    
            flen = fread(buf, sizeof(char), BUFSIZE, fp); // fp -> buf
            printf("read len: %lu
    ", flen);
            printf("Fread text:
    %s
    
    ", buf);
            fclose(fp);
    }
    
    // 将内存 buf 中的内容写入打开的文件 fp 中
    void Fwrite()
    {
            char buf[BUFSIZE] = BUFTEXT;
            size_t flen = 0;
            FILE *fp = fopen("./foo", "w+");
            flen = fwrite(buf, sizeof(char), strlen(buf), fp); // buf -> fp
            printf("Fwrite write len: %lu
    
    ", flen);
            fclose(fp);
    }
    
    // 将fp 换为 stdin 输入至 buf 中
    void Fscanf()
    {
            char buf[BUFSIZE];
            size_t flen = 0;
            FILE *fp = fopen("./foo", "r+");
            while(fscanf(fp, "%s", buf) != EOF) // fp -> buf, terminated by blank char
                    printf("Fscanf text:
    %s
    ", buf);
            printf("
    ");
            fclose(fp);
    }
    
    // C++ 文件流,输入至内存中,由于流遇到空格等空白符停止所以需循环将流中的内容全部输入至
    // 内存(string)中,直至返回 EOF  
    void Ifstream()
    {
            ifstream ifs("./foo");
            string buf;
            while (ifs >> buf) // ifs -> buf
                    cout <<"Ifstream: " <<  buf << endl;
    
            // char *str = new char[100];
            // ifs.read(str, 10);
            // whlile (getline(ifs, buf))
            //      cout << "Ifstream: " << buf << endl;
            ifs.close();
            cout << endl;
    }
    
    // fp 换为 stdout, buf 中的内容写入至 fp 中
    void Fprintf()
    {
            char buf[BUFSIZE] = "ioi ioi";
            int flen = 0;
            FILE *fp = fopen("./foo", "w+");
            flen = fprintf(fp, "%s", buf); // buf -> fp
            printf("Fprintf len: %d
    ", flen);
            fclose(fp);
    }
    
    void Ofstream()
    {
            ofstream ofs("./foo", ios::app | ios::out);
            string buf = "quick,,time go on";
            // ofs << buf;
            ofs.write(buf.c_str(), buf.size());
            ofs.close();
    }

    字符流的操作,内存至内存

    // 文件流 stdio 换为 str, 格式化输入
    void Sscanf()
    {
            char str[BUFSIZE] = BUFTEXT;
            char buf[BUFSIZE];
            sscanf(str, "%s", buf); // str -> buf
            printf("Sscanf text:
    %s
    
    ", buf);
    }
    
    // istringstream 对象 iss 绑定 buf,作为输入流输入至 word(string) 
    void Istringstream()
    {
            string buf = "hello world";
            string word;
    
            istringstream iss(buf); // buf -> iss
            while (iss >> word)     // iss -> word, repeatedly
                    cout << "Istringstream: " << word << endl;
    }
    
    // 与 sscanf() 类似, 格式化输出
    void Sprintf()
    {
            char str[BUFSIZE] = BUFTEXT;
            char buf[BUFSIZE];
            sprintf(buf, "%s", str); // str -> buf
            printf("Sprintf text:
    %s
    
    ", buf);
    }
    
    // 与 istringstream 类似
    void Ostringstream()
    {
            string buf = BUFTEXT;
            string word;
    
            ostringstream oss;
            oss << buf;             // buf -> oss
            word = oss.str();       // oss -> word
            cout << "Ostringstream: " << word << endl;
    }

    Linux 有无缓冲的 IO操作 (参考 UNP)

    // 无缓冲, 普通的 read() write() 并不难保证完成所需要传送的字符数
    ssize_t rio_readn(int fd, void *usrbuf, size_t n)
    {
            size_t nleft = n;
            ssize_t nread;
            char *bufp = usrbuf;
    
            while (nleft > 0) {
                    if ((nread = read(fd, bufp, nleft)) < 0) {
                            if (errno == EINTR)     // interrupted by sig handler return
                                    nread = 0;      // call read() again
                            else
                                    return -1;      // errno set by read()
                    } else if (nread == 0)
                            break;                  // EOF
                    nleft -= nread;
                    bufp += nread;
            }
    
            return (n - nleft);
    }
    
    // not buff read
    ssize_t rio_writen(int fd, void *usrbuf, size_t n)
    {
            size_t nleft = n;
            ssize_t nwritten;
            char *bufp = usrbuf;
    
            while(nleft > 0) {
                    if ((nwritten = write(fd, bufp, nleft)) <= 0) {
                            if (errno == EINTR)
                                    nwritten = n;
                            else
                                    return -1;
                    }
                    nleft -= nwritten;
                    bufp += nwritten;
            }
    
            return n;
    }
    
    // IO 缓冲区结构体
    typedef struct {
            int rio_fd;
            int rio_cnt;
            char *rio_bufptr;
            char rio_buf[RIO_BUFSIZE];
    } rio_t;
    // 与 read() 语义相同
    // 如果缓冲区为空会通过调用 read() 填满它
    static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
    {
            int cnt;
    
            while (rp->rio_cnt <= 0) {      // refill if buf is empty
                    rp->rio_cnt = read(rp->rio_fd, rp->rio_buf, sizeof(rp->rio_buf));
                    if (rp->rio_cnt < 0) {
                            if (errno != EINTR)
                                    return -1;
                    } else if (rp->rio_cnt == 0) {  // EOF
                            return 0;
                    } else {
                            rp->rio_bufptr = rp->rio_buf;   // reset buffer ptr
                    }
            }
    
            // copy min(n, rp->cnt) bytes from internal buf to user buf
            cnt = n;
            if (rp->rio_cnt < n)
                    cnt = rp->rio_cnt;
            memmove(usrbuf, rp->rio_bufptr, cnt);
            rp->rio_bufptr += cnt;
            rp->rio_cnt -= cnt;
    
            return cnt;
    }

    一点小结

    • 本质是操作对象的变化
    // C
    printf()  -- stdout     scanf()  -- stdin
    fprintf() -- FILE*      fscanf() -- FILE*
    sprintf() -- char*      sscanf() -- str
    // C++ 与上类似, 都具有缓冲区
    ostream                 istream
    ofstream                ifstream
    ostringstream           istringstream
    • 带有缓冲区的 rio_read() 有时效率很高,因为不必一直在内核-用户态之间切换
  • 相关阅读:
    回老家
    防疫针
    平安夜
    虎威威
    圣诞联欢会
    小老虎飞船
    电子积木
    打印
    周日大悦城
    又一年毕业季
  • 原文地址:https://www.cnblogs.com/shuqin/p/9450801.html
Copyright © 2020-2023  润新知