Linux系统编程 --- day2

目录

1. feof / ferror

2. fseek

3. ftell

4. 缓冲

5. 文件io

6. 操作函数

6.1 open

6.2 write

6.3 read

6.4 lseek

7. 练习


1. feof / ferror

feof ()  函数判断 : int feof(FILE *stream);
功能:判断当前参数stream的文件流指针是否到达文件结尾,如果到达文件结尾则返回真,否则返回假
注意:该操作一定要在一次IO操作之后判断。
参数:stream 要判断结尾的文件流对象
         返回值:成功到达结尾是 真 , 否则 是假

ferror : 检测一个流是否出错

if (feof(fp)) {
printf("到达文件末尾!\n");
} else {
printf("未到达文件末尾!\n");
}

if (ferror(fp)) {
printf("出错!\n");
clearerr(fp);
} else {
printf("未出错!\n");
}

2. fseek

int fseek(FILE *stream, long offset, int whence);
功能:将stream流文件中的文件指针从whence位置开始,偏移offset字节的长度。
参数:stream  要移动文件指针的目标文件流对象。
注意:不支持设备文件,一般用于普通文件。
          offset  要在文件内偏移的距离,单位字节。
          如果值为整数,则向文件末尾偏移
          如果值为负数,则向文件开头偏移
          whence  偏移的起始位置,由系统定义的三个宏开始。
           SEEK_SET  文件的开头位置 
          SEEK_CUR  文件的当前位置
          SEEK_END  文件的末尾位置
返回值:
成功: 返回 0
失败:  -1;
如果从文件的指定位置向后偏移过程中已经超过了文件的当前末尾位置,则会自动以'\0'来填充文件内容,从而形成一种被称为"空洞文件" 的特殊文件。

#include <stdio.h>

int main(int argc, char *argv[])
{
    
    FILE* fp = fopen("./01fopen.c","r");
    if(NULL == fp)
    {
        printf("fopen error\n");
        return 1;
    }

    int ret = fseek(fp,10,SEEK_SET);
    if(-1 == ret)
    {
        printf("fseek error\n");
        return 1;
    }

    char buf[512]={0};
    fgets(buf,sizeof(buf),fp);
    printf("buf is %s\n",buf);

    fclose(fp);


    return 0;
}

3. ftell

long ftell(FILE *stream);rewind(fp);
功能:获取当前文件流指针的具体位置,一般以文件开头到当前指针的字节数为返回值。
参数:stream 要返回指针距离的文件流对象
返回值:成功 获取到的距离长度,单位是字节;失败 -1;

#include <stdio.h>

int main(int argc, char *argv[])
{
    
    FILE* fp = fopen("./2.png","r");
    if(NULL == fp)
    {
        return 1;
    }

    fseek(fp,0,SEEK_END);
    long size = ftell(fp);
    fclose(fp);
    printf("size is %ld\n",size);
    return 0;
}


 

4. 缓冲

(1)行缓冲

1k, terminal,主要用于人机交互stdout
缓存区满或者遇到\n刷新 1024,行缓存多是关于终端的一些操作
1.遇到\n刷新
2.缓存区满刷新(1k = 1024)
3.程序结束刷新
4.fflush刷新  fflush(stdout);

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    /* 1. 如果在hello后面加上 '\n' ,就会在屏幕上显示
    printf("hello");
    while(1)
    sleep(1);
    */ 

    /* 2. i 为超过1024,则在屏幕上显示前1024个a
    int i=0;
    for(i=0;i<1025;i++)
    {
    
        //printf("a");
        fputc('a',stdout);//  stdin stdout stderr 
    }

    while(1)
    sleep(1);
    */ 

    /*3. 程序结束
    printf("hello");
    */ 

    /* 4. fflush 刷新
    printf("hello");
    fflush(stdout);
    while(1)
    sleep(1);
    return 0;
}


(2)全缓冲

4k,主要用于文件的读写
缓存区满刷新缓存区 4096,对普通文件进行标准IO操作,建立的缓存一般为全缓存
刷新条件:
1.缓存区满刷新
2.程序结束刷新
3.fflush来刷新  fflush(fp);

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    FILE* fp = fopen("1.txt","w");
    if(NULL == fp)
    {
        return 1;
    }

    /* 1
    char buf[]="hello";
    fputs(buf,fp);

    while(1)
        sleep(1);
    */ 


    /*2 
    int i=0;
    for(i = 0 ;i < 4097;i++)
    {
        fputc('a',fp);
    }
    while(1)
        sleep(1);
    return 0;
    */

    /*3
    char buf[]="hello";
    fputs(buf,fp);
    return 0;
    */ 

    char buf[]="hello";
    fputs(buf,fp);
    fflush(fp);

    while(1)
        sleep(1);

    return 0;

}

(3)无缓冲

0 k  主要用于出错处理信息的输出 stderr ,不对数据缓存直接刷新
printf( ); =>  stdout 
fprintf(strerr,"fopen error %s",filename);
界面交互 出错处理:使用gdb查看,FILE结构体,或使用写入数据测试缓冲区。
缓冲区的大小是可以设置

5. 文件io

操作系统为了方便用户使用系统功能而对外提供的一组系统函数。称之为 系统调用  其中有个  文件IO,一般都是对设备文件操作,当然也可以对普通文件进行操作。
一个基于Linux内核的没有缓存的IO机制。

特性:
1.没有缓存区
2.操作对象不在是流,而是文件描述符  FILE*    int 0-1023
3.文件描述符
很小的非负的整数 int   0~1023
内核每打开一个文件就会获得一个文件 描述符
 每个程序在启动的时候操作系统默认为其打开 三个描述符与流对象匹配:
  0 ==> STDIN_FILENO ==> stdin
  1 ==>STDOUT_FILENO == >stdout
  2 ==>STDERR_FILENO ==> stderr
注:因为0,1,2被这三个描述符占了,所以我们写的文件一般从3开始。

6. 操作函数

6.1 open

int open(const char *pathname, int flags,int mode);
功能:获得一个文件描述符
参数:
pathname : 文件名
flags:
O_RDONLY (只读)

O_WRONLY(只写)               // 三选一
O_RDWR     (读写)


O_CREAT, 创建文件 
O_EXCL    需要和O_CREAT同时使用,表示新建的文件不能存在,成功,否则open就会失败
O_NOCTTY   不是终端设备
O_TRUNC      文件内容清空(如果写上这个标志位,就要指定模式,对普通文件传0666)
O_APPEND    追加
O_ASYNC      异步io,什么时候io不确定,
O_NONBLOCK  非阻塞 

返回值:成功返回文件描述符,失败返回-1

fopen    open 
w          O_WRONLY | O_CREAT | O_TRUNC 
w+        O_RDWR | O_CREAT | O_TRUNC 
r            O_RDONLY 
r+          O_RDWR
a            O_WRONLY | O_CREAT | O_APPEND
a+          O_RDWR | O_CREAT | O_APPEND

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
    int fd = open("1.txt",O_WRONLY| O_CREAT|O_TRUNC,0666);    
    if(-1 == fd)
    {
        fprintf(stderr,"open error\n");
        return 1;
    }
    printf("fd is %d\n",fd);
    return 0;
}

6.2 write

ssize_t write(int fd,  const  void *buf, size_t count);
功能 : 通过文件描述符向文件中写一串数据
参数:
fd : 文件描述符
buf : 要写入文件的字符串的首地址
count : 要写入字符的个数(实际有效长度,字符一般用strlen)
返回值 : 成功返回实际写入的个数,失败返回 -1

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
    int fd = open("1.txt",O_WRONLY| O_CREAT|O_TRUNC,0666);    
    if(-1 == fd)
    {
        fprintf(stderr,"open error\n");
        return 1;
    }
    printf("fd is %d\n",fd);
    char buf[512]="hello";
    int ret = write(fd,buf,strlen(buf));
    if(-1 == ret)
    {
        fprintf(stderr,"write error\n");
        return 1;
    }

    close(fd);
    return 0;
}

6.3 read

ssize_t read(int fd, void *buf, size_t count);
功能 : 通过文件描述符读取文件中的数据
参数:
fd : 文件描述符
buf : 存放数据空间的首地址
count : 要读到数据的个数
返回值:成功返回读到数据的个数,失败返回-1,读到文件结尾返回0

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    int fd = open("1.txt",O_RDONLY);    
    if(-1 == fd)
    {
        fprintf(stderr,"open error\n");
        return 1;
    }
    printf("fd is %d\n",fd);
    char buf[512]={0};
    while(1)
    {
        int ret = read(fd,buf,sizeof(buf));
        if(ret<=0)                            // 表示读完或者错误
        {
            break;
        }
        printf("%s\n",buf);
    }

    close(fd);
    return 0;
}

6.4 lseek

off_t lseek(int fd, off_t offset, int whence);
功能:定位光标的位置
参数:
fd : 文件描述符
offset : 偏移量
正 : 向后偏移
负 : 向前偏移
零 : 不偏移


whence:
SEEK_SET
SEEK_CUR
SEEK_END
返回值 :成功返回偏移量,失败返回-1

注意:
1、不支持O_APPEND的追加模式,无法生成空洞文件。
2、lseek函数执行失败,文件指针还在偏移前的位置。
3、lseek函数在设备文件上偏移无效。
 

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
    int fd = open("1.txt",O_RDWR);    
    if(-1 == fd)
    {
        fprintf(stderr,"open error\n");
        return 1;
    }
    off_t off = lseek(fd,15,SEEK_SET);
    printf("off %ld\n",off);
    char buf[]="hello";
    write(fd,buf,strlen(buf));

    printf("fd is %d\n",fd);
    close(fd);
    return 0;
}

7. 练习

用read 和 write 写出 复制文件的功能

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

int main(int argc, char *argv[])
{
    if(argc < 3)
    {
        fprintf(stderr,"usage:./a.out srcfile dstfile\n");
        return 1;
    }
    int src_fd = open(argv[1],O_RDONLY);    
    int dst_fd = open(argv[2],O_WRONLY| O_CREAT|O_TRUNC,0666);    
    if(-1 == src_fd ||-1 == dst_fd)
    {
        fprintf(stderr,"open error\n");
        return 1;
    }
    while(1)
    {
        char buf[512]={0};
        int rd_ret = read(src_fd,buf,sizeof(buf));
        if(rd_ret<=0)
        {
            break;
        }
        write(dst_fd,buf,rd_ret);
    }

    close(dst_fd);
    close(src_fd);
    return 0;
}

  • 31
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值