【C语言】文件操作

目录

一.什么是文件

1.1定义

1.2文件名

二.文件的打开与关闭

2.1文件指针

2.2文件的打开与关闭

fopen

fclose

三.文件的顺序读写

顺序读写函数

fputc(字符输出函数)

fgetc(字符输入函数)

fputs(文本行输出函数)

fgets(文本行输入函数)

fprintf(格式化输出函数)

fscanf(格式化输入函数)

fwrite(二进制输出)

fread(二进制输入)

流:

scanf,printf和fscanf,fprintf区别

四.文件的随机读写

4.1 fseek

4.2 ftell

4.3  rewind


比如:当我们写了一个通讯录,运行起来后可以在里头 增减数据,而一旦退出程序后,其中的数据就会不在了,只 能在下次重新输入数据,这样的通讯录明显不符合我们的需求。

So当我们需要将数据做到持久化时,就需要使用文件将数据存放在电脑的硬盘上

一.什么是文件

1.1定义

磁盘上的文件是文件

在程序设计中,功能性的将文件一般分为:程序文件,数据文件

  • 程序文件:包括 源程序文件(后缀为 .c),目标文件(windoes环境后缀为 .obj),可执行文件(windoes环境后缀为 .exe
  • 数据文件:文件的内容不一定是程序,而是程序在运行时读写的数据, 比如程序运行需要从中读取数据的文件,或输出内容的文件。

1.2文件名

一个文件需要一个唯一的文件标识,以便进行识别和引用

文件名:文件路径+文件名主干+文件后缀

如:c:\code\test.txt

二.文件的打开与关闭

2.1文件指针

每个被使用的文件都会在内存中开辟出一个相应的文件信息区,其用来存放文件的相关信息(如文件名、文件状态 及 文件当前位置 等)。这些信息是保存在一个结构体变量中的,该结构体类型是由系统申明的,其名为 FILE

注意:文件和文件信息区是关联的,文件已改变则文件信息区也会发生改变

注意:

  1. FILE结构在不同的C编译器下设计和实现可能是有所差异的,但是大同小异
  2. ​每当打开一个文件时,系统会根据文件的情况自动创建一个 FILE 结构的变量,并填充其中的信息。我们不用关其细节
  3. 一般可通过一个 FILE 的指针来维护这个 FILE 结构的变量

创建一个FILE*的指针变量:


FILE* pf;  //文件指针变量


//定义 pf 是一个指向 FILE 类型的指针变量,可以使 pf 指向某个文件的文件信息区(是一个结构体变量,可通过该文件信息区的信息就能够访问该文件。

可通过文件指针变量找到与其相关联的文件

2.2文件的打开与关闭

文件在读写前应该先用  fopen打开文件,使用结束后用  fclose关闭文件

fopen

  • 如果文件成功打开,该函数将返回指向​FILE​对象的指针;失败则返回空指针

方式

描述

"r"

打开一个已有的文本文件,只允许读取文件;如果这个文件不存在或未找到,则打开失败,报错

"w"

打开一个空文件,为文件;如果文件不存在,则会创建一个新文件;如果这个文件里有内容,该文件内容将被销毁

"a"

追加写入文件;如果文件不存在,则会创建一个新文件。

"r+"

打开一个文本文件,允许读写文件。

"w+"

创建一个空文件;允许读写文件。如果文件已存在,则文件内容被销毁;如果文件不存在,则会创建一个新文件。

"a+"

在文件尾进行读写   ;如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只 能是追加模式。

fclose

#include<stdio.h>
int mainn()
{
  FILE* pf = fopen("test.txt","w");
  if(pf == NULL)
  {
    perror("fopen");
    return 1;
  }
  //开写文件
  //。。。。。。。。。。。。
  //关闭文件
  fclose(pf);
  pf = NULL;
  
}

三.文件的顺序读写

顺序读写函数

功能

函数名

适用于

字符输入函数

fgetc

所有输入流

字符输出函数

fputc

所有输出流

文本行输入函数

fgets

所有输入流

文本行输出函数

fputs

所有输出流

格式化输入函数

fscanf

所有输入流

格式化输出函数

fprintf

所有输出流

二进制输入

fread

文件

二进制输出

fwrite

文件

fputc(字符输出函数)

#include <stdio.h>
int main() 
{
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }
    // 写文件
    fputc('b', pf);
    fputc('y', pf);
    fputc('e', pf);
 
    // 关闭文件
    fclose(pf);
    pf = NULL;
 
    return 0;
}

运行后不会直接看见bye.

而当我们打开文本后可以看到:

fgetc(字符输入函数)

  • 从流中读取一个字符位置标识符向前移动一(字符必须为一个无符号字符)
  • 参数为 指向标识输入流的​FILE​对象的指针。
  • 如果读取成功会返回相应的ASCII码值读取失败它会返回一个EOF

//从文件里读取

#include <stdio.h>
int main() 
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }
    // 写文件
    int ret = fgetc(pf);
    printf("%c\n",ret);
    ret = fgetc(pf);
    printf("%c\n",ret);
    ret = fgetc(pf);
    printf("%c\n",ret);
    // 关闭文件
    fclose(pf);
    pf = NULL;
 
    return 0;
}

//从标准输入流 (键盘)读取

#include <stdio.h>
int main() 
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }
    // 写文件
    int ret = fgetc(stdin);
    printf("%c\n",ret);
    ret = fgetc(stdin);
    printf("%c\n",ret);
    ret = fgetc(stdin);
    printf("%c\n",ret);
    // 关闭文件
    fclose(pf);
    pf = NULL;
 
    return 0;
}

fputs(文本行输出函数)

  • str指向流的C 字符串写入

#include <stdio.h> 
int main()
{
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }
    //写文件 ——按照行来写
    fputs("abcdef\n", pf);
    fputs("zxcvbnm\n", pf);
 
    //关闭文件
    fclose(pf);
    pf = NULL; 
    return 0;
}

fgets(文本行输入函数)

  • 读取时由于最后会使用一个进行\0的读取,所以一次最多读取n-1个

#include <stdio.h>
int main()
{
    char arr[10] = {0}; // 存放处
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL)
    {
        perror("fopen");
        return 1;
    }
    //读文件 - 按照行来读
    fgets(arr, 4, pf);
    printf("%s\n", arr);
    fgets(arr, 4, pf);
    printf("%s\n", arr);
 
    // 关闭文件
    fclose(pf);
    pf = NULL;
    return 0;
}

fprintf(格式化输出函数)

  • 将一个格式化的数据写到文件里
#include <stdio.h>
struct S
{
    char arr[10];
    int num;
    float wb;
}; 
int main()
{
    struct S s = { "qazxsw", 10, 8.2f };
    // 对格式化的数据进行 写文件
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL) 
    {
        perror("fopen");
        return 1;
    }
    // 写文件
    fprintf(pf, "%s %d %f", s.arr, s.num, s.wb);
 
    // 关闭文件
    fclose(pf);
    pf = NULL;
    return 0;
}

fscanf(格式化输入函数)

#include <stdio.h>
 
struct S
{
    char arr[10];
    int num;
    float wb;
};
int main()
{
    struct S s = { "qazxsw", 10, 8.2f };
 
    // 对格式化的数据进行 写文件
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) 
   {
        perror("fopen");
        return 1;
    }
    // 读文件
   fscanf(pf,"%s %d %f", s.arr, &(s.num), &(s.wb));
 
   //打印
   printf("%s %d %f\n", s.arr ,s.num ,s.wb) ;
    // 关闭文件
    fclose(pf);
    pf = NULL;
    return 0;
}
//qazxsw 10 8.200000

fwrite(二进制输出)

  • 写数据到流中

#include <stdio.h>
 
struct S
{
    char arr[10];
    int num;
    float wb;
};
int main()
{
    struct S s = { "qazxsw", 10, 8.2f };
   //二进制形式  写 
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL) 
   {
        perror("fopen");
        return 1;
    }
    // 写文件
    fwrite(&s, sizeof(struct S), 1, pf) ;
     
    // 关闭文件
    fclose(pf);
    pf = NULL;
    return 0;
}

在记事本中打开test.txt,可以看到除了字符串,其他是乱码:

得要搭配fread函数来看

fread(二进制输入)

  • 从流中读取数据到ptr

#include <stdio.h>
 
struct S
{
    char arr[10];
    int num;
    float wb;
};
int main()
{
    struct S s = { "qazxsw", 10, 8.2f };
   //二进制形式  读
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) 
   {
        perror("fopen");
        return 1;
    }
    // 读文件
    fread(&s, sizeof(struct S), 1, pf) ;
    printf("%s %d %f",s.arr ,s.num ,s.wb) ;
   
    // 关闭文件
    fclose(pf);
    pf = NULL;
    return 0;
}
//qazxsw 10 8.200000

  小结:fwite写,fread读

流:

c语言程序,只要运行,就默认打开3个流(均为FILE*):

stdin——标准输入流——从键盘  输入

stdout——标准输出流——输出至  屏幕

stderr——标准错误流——输出至 屏幕

例子:使用stdout下

scanf,printf和fscanf,fprintf区别

scanf   针对标准输入的格式化的输入语句 —— stdin

fscanf  针对所有输入流的格式化的输入语句 —— stdin/文件

printf 针对标准输出的格式化的shuchuyuju输出语句 —— stdout

fprintf 针对所有输入流的格式化的输出语句 —— stdout/文件

四.文件的随机读写

4.1 fseek

  • 根据文件指针的位置和偏移量来定义文件指针

  • 偏移量为负数——表示向后多少;正数——表示向前多少
#include <stdio.h>
 
int main(void) 
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) 
    {
        perror("fopen");
        return 1;
    }
 
    // 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);
    
    ch = fgetc(pf);
    printf("%c\n", ch);
    
    ch = fgetc(pf);
    printf("%c\n", ch);
 
    // 关闭文件
    fclose(pf);
    pf = NULL;
 
    return 0;
}
//q a z 

当加入fseek函数:

#include <stdio.h>
 
int main(void) 
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) 
    {
        perror("fopen");
        return 1;
    }
 
    // 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);
    
    fseek(pf ,-1 ,SEEK_CUR);//往后1个字节
    
    ch = fgetc(pf);
    printf("%c\n", ch);
    
    ch = fgetc(pf);
    printf("%c\n", ch);
 
    // 关闭文件
    fclose(pf);
    pf = NULL;
 
    return 0;
}
//q q a

4.2 ftell

  • 返回文件指针相对于起始位置的偏移量
#include <stdio.h>
 
int main(void) 
{
    FILE* pf = fopen("test1.txt", "r");
    if (pf == NULL) 
    {
        perror("fopen");
        return 1;
    }
 
    // 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);
    
    fseek(pf ,-2 ,SEEK_END);
    
    ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    printf("%c\n", ch);
 
    int ret = ftell(pf);
    printf("%d\n",ret);
    
    // 关闭文件
    fclose(pf);
    pf = NULL;
 
    return 0;
}
//a e f 6

4.3  rewind

  • 让文件指针的位置回到文件的起始位置
#include <stdio.h>
 
int main(void) 
{
    FILE* pf = fopen("test1.txt", "r");
    if (pf == NULL) 
    {
        perror("fopen");
        return 1;
    }
 
    // 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);
    
    fseek(pf ,-2 ,SEEK_END);
    
    ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    printf("%c\n", ch);
 
    int ret = ftell(pf);
    printf("%d\n",ret);
    
    //让文件回到起始位置 
    rewind(pf);
    ch = fgetc(pf);
    printf("%c\n", ch);
    
    // 关闭文件
    fclose(pf);
    pf = NULL;
 
    return 0;
}
//a e f 6 a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值