文件I/O详解

文件IO(input/output)

标准C文件I/O

fopen(打开文件)

  • 函数原型

    FILE *fopen(const char *path, const char *mode);

  • 参数说明

    path[入参] 将要打开的文件的路径
    mode[入参] 文件打开方式
    “r” 只读方式打开
    “w” 只写方式打开,如果文件不存在,会新建,存在就清空
    “r+” 可读可写方式打开,不清空,也不新建
    “w+” 可读可写方式打开,清空,新建
    “a+” 可读可写方式打开, 追加输入的方式,不清空,新建
    入参: 输入参数(调用者传递给被调用者的值, 被调用者不能改), 带const的
    出参: 输出参数(被调用者传递给调用者的值, 被调用者通常会改 参数值), 不带const
    返回值 :
    成功: 返回一个有效地址
    失败: 返回 NULL

  • 返回值

    返回值 :

    成功: 返回一个有效地址

    失败: 返回 NULL

  • 使用例子

    #include <stdio.h>
    int main()
    {
    FILE *fp = fopen(“hello.c”, “r”);
    if(fp != NULL)
    {
    printf(“open success\n”);
    }
    else
    {
    printf(“open failed\n”);
    }
    }
    例2
    #include <stdio.h>
    int main()
    {
    FILE *fp = fopen(“hello1111.c”, “w”);
    if(fp != NULL)
    {
    printf(“open success\n”);
    }
    else
    {
    printf(“open failed\n”);
    }
    }

fgetc(从文件中读出一个字符,必须先调用fopen)

fgetc 功能:从文件中读出一个字符,必须先调用fopen,然后才能读文件
int fgetc(FILE *stream);
参数: FILE *stream , fopen的返回值
返回值:
EOF 读失败, 否则,返回有效字符

char ch = fgetc(fp);
返回值:读出的字符

fgets(读取文件,每次读取一行)

fgets(读取文件,每次读取一行)
char *fgets(char *s, int size, FILE *stream);
参数1: char *s, 读出的数据存放的位置
2: 将要读出的数据的最大值(最多读多少个字符)
3: 文件指针
返回值:
NULL 读到了文件尾,或者读取失败
非NULL, 读取成功,返回读到数据存放的位置
fgets(buf, 100, fp);

#include <stdio.h>
int main()
{
FILE *fp = fopen(“hello.c”, “r”);
if(fp != NULL)
{
char buf[100] = { 0 };
while(fgets(buf, sizeof(buf), fp) != NULL)
{ //fgets 碰到 ‘\n’ 就读出此行,数据放到buf中
//如果一行多于 sizeof(buf), 最多读出sizeof(buf) - 1 个,因为最后一个是 ‘\0’
printf(“%s”, buf);
}
}
}

练习:统计文件行数
#include <stdio.h>
int main()
{
FILE *fp = fopen(“hello.c”, “r”);
if(fp != NULL)
{
int count = 0;
char buf[1000] = { 0 };
while(fgets(buf, sizeof(buf), fp) != NULL)
{
count++;
}
printf(“count is %d\n”, count);
}
}

fputs(往文件里写数据,写一行 ,和fgets正好相反)

fputs(功能:往文件里写数据,写一行) //和fgets正好相反

fputs(const char *s, FILE *stream);
参数 s, 是要写到文件中的数据存放位置
stream fopen的返回值
例: 从键盘输入5行,写到文件中
#include <stdio.h>

int main()
{
int i;
char buf[100] = { 0 };
FILE *fp = fopen(“cc.cc”, “w”);
if(fp != NULL)
{
for(i = 0; i < 5; i++)
{
char buf1[100] = { 0 };
scanf(“%s”, buf);
sprintf(buf1, “%s\n”, buf); //格式化输出 内容到 buf1中
fputs(buf1, fp);
}
fclose(fp);
}
}

fflush

fflush(fp); //强行将缓冲区中的数据写入文件

fread(读文件)

  • 函数原型

    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

  • 参数说明

    参数说明
    ptr [出参]: 读出的数据,存入的位置
    size : 一块的大小
    nmemb : 将要读出的块数
    stream : fopen的返回值

  • 返回值

    返回值:
    实际读到的块数 (不是以字节为单位)
    <= 0 读到了文件尾,或失败
    int a[10];
    fread(a, sizeof(int), 10, fp); //读出10个int

    char a[100];
    fread(a, sizeof(char), 100, fp); //读出100个char

  • 使用例子

    //例子1次读1000字节//
    #include <stdio.h>
    int main()
    {
    char buf[1000] = { 0 };
    FILE *fp = fopen(“hello.c”, “r”);
    fread(buf, sizeof(char), sizeof(buf), fp);
    printf(“%s”, buf);
    }
    //例子分批次读///
    #include <stdio.h>
    #include <string.h>
    int main()
    {
    char buf[50] = { 0 };
    FILE *fp = fopen(“hello.c”, “r”);
    while(fread(buf, sizeof(char), sizeof(buf), fp) > 0)
    {
    printf(“%s”, buf);
    memset(buf, 0, sizeof(buf));
    }
    }
    130—>

    1. 50
    2. 50
    3. 30 但是,buf中还剩20个上次读的数据

fwrite(写文件)

  • 函数原型

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

  • 参数说明

    参数:
    ptr 将要写入的数据的首地址
    size 一块的大小
    nmemb 将要写入块数
    stream fopen的返回值

  • 返回值

    返回值: 实际写入的块数
    int a[10] = {1,2,3,4,5,6,7,8,9,10};
    fwrite(a, sizeof(int), 10, fp); //向文件中写入10个int
    char buf[100] = “hello”;
    fwrite(a, sizeof(char), 100, fp);

    文件分为两种类型
    1 可以用记事本打开,并且不是乱码的,是可见字符,这种文件叫文本文件
    hello.c
    a.txt

    2 二进制文件,可执行文件,如果用记事本打开,是乱码
    图片
    可执行文件
    word文件
    /fwrite可以向文件中写入二进制数据

  • 使用例子

    ///例子:将1,2,3,4,5,6,…,9 写入文件 write.c
    #include <stdio.h>
    int main()
    {
    int i;
    FILE *fp = fopen(“cc.cc”, “w”);
    for(i = 1; i < 10; i++)
    {
    fwrite(&i, sizeof(int), 1, fp); //写入一个int(4字节)
    }
    }
    读出 read.c
    #include <stdio.h>
    int main()
    {
    int i, a[10] = { 0 };
    FILE *fp = fopen(“cc.cc”, “r”);
    int len = fread(a, sizeof(int), 10, fp);
    printf(“len is %d\n”, len); //len ? 9
    for(i = 0; i < 10; i++)
    {
    printf(“%d\n”, a[i]); //a ? 1,2,3,4,5,6,7,8,9,0
    }
    }

fseek(让文件指针到某个指定的位置)

  • 函数原型

    int fseek(FILE *stream, long offset, int whence);

  • 参数说明

    参数
    stream fopen的返回值
    offset(偏移量) 100 向后100字节 -100向前100字节
    whence SEEK_END 到文件尾
    SEEK_SET 到文件头
    SEKK_CUR 到文件当前位置

    fseek(fp, -100, SEEK_END); // 文件指针指向 文件尾前100字节
    fseek(fp, 100, SEEK_SET); // 文件指针指向 文件头后100字节
    fseek(fp, 100, SEEK_CUR); // 文件指针指向 文件当前位置后100字节

  • 使用例子

    #include <stdio.h>
    int main ()
    {
    char buf[10] = { 0 };
    FILE *fp = fopen(“hello.c”, “r”);
    if(fp != NULL)
    {
    fseek(fp, -10, SEEK_END);
    fread(buf, 1, 10, fp);
    printf(“%s”, buf);
    }
    }

fclose(关闭文件)

fclose(fp); 关闭文件,如果缓冲区中有数据,会将缓冲区中的数据强制写入文件

标准C文件I/O是带缓冲区机制的,缓冲区是Linux系统在打开文件时,自动新建的

如果文件打开失败,也不要关闭

Linux文件I/O

库文件

  • 动态链接库

  • 静态库

    区别:

    1. 从占用内存及硬盘空间的角度
      静态链接生成的可执行文件大,同时运行多份时,占用的内存多

    动态链接生成的可执行文件小,运行多份时,只有一个库,占用内存少
    2) 从 软件升级的角度
    静态链接每个应用程序都需要升级
    动态链接,只升级库函数即可 (更易于升级)

    1. 从独立性的角度
      静态链接好,不依赖于库 (如果看到有些可执行文件 50M 比较大,这种通常是静态链接)

    结论: windows 和 linux系统的可执行文件多数都采用动态链接
    动态链接一般需要安装文件

库函数

缓冲区机制

缓冲区机制:
一个快速设备 和 一个慢速设备通信 : 通常需要缓冲区

cpu(快速) 和 硬盘(慢速)进行通信, 需要由 内存导一下

//linux 输出(行缓冲输出 \n, + 全缓冲输出(够了 1024 字节,一起输出))

#include <stdio.h>

int main()
{
while(1)
{
printf(“hello”);
sleep(1); //延时1秒
}
}

默认缓冲区大小是1024字节

用fgets和fputs实现复制文件

cp a.c b.c //将a.c中数据写到b.c中
//./a.out a.c b.c
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc < 3)
{
printf(“param error, like this: ./a.out hello.c a.c\n”);
return -1;
}
FILE *fpr = fopen(argv[1], “r”);
if(fpr != NULL)
{
char buf[100] = { 0 };
FILE *fpw = fopen(argv[2], “w”);
while(fgets(buf, sizeof(buf), fpr) != NULL)
{
fputs(buf, fpw);
}
fclose(fpr);
fclose(fpw);
}
}

用fread和fwrite完成文件copy

练习:用fread 和 fwrite完成文件copy,
/分批次读///
#include <stdio.h>
int main(int argc, char *argv[])
{
if(argc < 3)
{
printf(“param error, like this: ./a.out a.c b.c\n”);
return -1;
}
FILE *fpr = fopen(argv[1], “r”);
if(fpr != NULL)
{
char buf[50] = { 0 };
int len;
FILE *fpw = fopen(argv[2], “w”);
while((len = fread(buf, sizeof(char), 50, fpr)) > 0)
{
fwrite(buf, sizeof(char), len, fpw);
}
fclose(fpr);
fclose(fpw);
}
}

XMind: ZEN - Trial Version

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值