04、LinuxC -- 系统调用 wirte,read,lseek函数

wirte函数原型:

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

作用:

        write( ) 会把参数buf所指的内存写入count个字节到参数fd所指的文件内。当然,文件读写位置也会随之移动。

返回值:

        如果顺利,write( )会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中

1、EINTR:此调用被信号所中断。
2、EAGAIN:当使用不可阻断I/O时(O_NONBLOCK),若无数据可读取则返回此值。
3、EADF:参数fd非有效的文件描述词,或该文件已关闭

---------------------------------------------------------------------------------------------------------------------------------

read函数原型:

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

作用:

        read( ) 会把参数 fd 所指的文件传送 count 个字节到 buf 指针所指的内存中。若参数 count 为0,则read( )不会有作用并返回0。返回值为实际读取到的字节数,

        如果返回 0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动

返回值:

         如果顺利,read( ) 会返回实际读到的字节数,最好能将返回值与参数count作比较,若返回的字节数比要求读取的字节数少,则有可能读到了文件尾、从管道(pipe)或终端机读取,或者是read( )被信号中断了读取动作。当有错误发生时则返回-1,错误代码存入errno中,而文件读写位置则无法预期

1、EINTR:此调用被信号所中断。
2、EAGAIN:当使用不可阻断I/O时(O_NONBLOCK),若无数据可读取则返回此值。
3、EBADF:参数fd非有效的文件描述词,或该文件已关闭

---------------------------------------------------------------------------------------------------------------------------------

lseek函数原型

        off_t lseek(int fildes,off_t offset ,int whence);

作用

        每一个已打开的文件都有一个读写位置,在打开文件时通常其读写位置指向文件开头,若是以附加的方式打开文件(如O_APPEND),则读写位置会指向文件尾。

        当read( ) 或write( )时,读写位置会随之增加,lseek( )便是用来控制该文件的读写位置的。

        参数fildes为已打开的文件描述词;

        参数offset为根据参数whence来移动读写位置的位移数,

        参数whence为下列其中一种。

1、SEEK_SET:参数offset即为新的读写位置。
2、SEEK_CUR:以目前的读写位置往后增加offset个位移量。
3、SEEK_END:将读写位置指向文件尾后再增加offset个位移量。

当 whence 值为SEEK_CUR或SEEK_END时,参数offet允许负值的出现。下列是较特别的使用方式:

1、欲将读写位置移到文件开头时,lseek(int fildes,0,SEEK_SET)。
2、欲将读写位置移到文件尾时,lseek(int fildes,0,SEEK_END)。
3、想要取得目前文件位置时,lseek(int fildes,0,SEEK_CUR)

返回值      

        当调用成功时则返回目前的读写位置,也就是距离文件开头多少个字节;若有错误则返回-1,errno会存放错误代码

Linux系统不允许lseek( )对tty装置作用,此项动作会令lseek( )返回ESPIPE

---------------------------------------------------------------------------------------------------------------------------------

读一行写一行 实现文件复制 demo

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

int read_line(int fd, void *ptr, int max_len)
{
    int n_r;
    int i = 0;
    char *buffer = (char *)ptr;
    char temp;

    for (i = 0; i < max_len; i++)
    {
        n_r = read(fd, &temp, 1);
        if (n_r < 0)
        {
            perror("read error:");
        }

        if (n_r == 0)
        {
            if (i == 0)
            {
                return 0;
            }
            return i;
        }

        if (temp == '\n')
        {
            buffer[i] = temp;
            buffer[i + 1] = '\0';
            return i + 1;
        }

        else
        {
            buffer[i] = temp;
        }
    }
    buffer[i] = '\n';

    buffer[i + 1] = '\0';

    return i;
}

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        printf("Please input file name!\n");
        exit(1);
        // void exit(int status)  头文件 --- <stdlib.h>  status --- 给父进程的返回值
        // 关闭所有文件,终止正在执行的进程
        // exit(1) 表示异常退出
        // exit(x) x != 0 都表示异常退出
        // exit(0) 表示正常退出
    }

    int fd;
    int to_fd;

    char buffer[1024];

    if ((fd = open(argv[1], O_RDWR | O_CREAT, 0655)) < 0)
    {
        perror("open file error:");
        exit(1);
    }

    if ((to_fd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0655)) < 0)
    // O_TRUNC 会将文件原本的内容全部丢弃,文件大小变为 0。
    {
        perror("open file error:");
        exit(1);
    }

#if 0
    lseek(fd,0,SEEK_SET);
    // SEEK_CUR --  表示当前位置
    // SEEK_END --  表示结尾位置
    // SEEK_SET --  从文件开始
    // 返回值 成功反悔当前位置到开始位置的长度
    // 失败返回-1 并设置error
    memset(buffer,0,sizeof(buffer));
    
    while(read_line(fd,buffer,sizeof(buffer)-1) != 0)  //遇到“/n”或者缓冲最大值时,停止读取数据
    {
        printf("%s\n",buffer);
        memset(buffer,0,sizeof(buffer));
    }
#endif

    while (read_line(fd, buffer, sizeof(buffer) - 1) != 0)
    {
        write(to_fd, buffer, strlen(buffer));
        memset(buffer, 0, sizeof(buffer));
    }
    close(fd);
    return 0;
}

运行结果:

superlan@GodFather:~/C_Language/file_io$ ./a.out open.c open.txt
superlan@GodFather:~/C_Language/file_io$ ls
a.out  creat.c  lseek_return.c  open.c  open.txt  read_line_by_line.c  read_line.c  three_hello.c
superlan@GodFather:~/C_Language/file_io$ ls -l
总计 48
-rwxrwxr-x 1 superlan superlan 16392  7月 30 21:02 a.out
-rw-rw-r-- 1 superlan superlan   658  7月 30 14:47 creat.c
-rwxrwxrwx 1 superlan superlan   442  4月  5 20:56 lseek_return.c
-rw-rw-r-- 1 superlan superlan   476  7月 30 16:25 open.c
-rw-r-xr-x 1 superlan superlan   476  7月 30 21:06 open.txt
-rwxrwxrwx 1 superlan superlan  2709  7月 30 21:04 read_line_by_line.c
-rwxrwxrwx 1 superlan superlan   853  7月 30 21:01 read_line.c
-rwxrwxrwx 1 superlan superlan  1317  4月  6 16:12 three_hello.c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值