C语言文件读写操作总结

文件的基本操作

      文件的打开操作 fopen 打开一个文件
      文件的关闭操作 fclose 关闭一个文件
      文件的读写操作 fgetc 从文件中读取一个字符
              fputc 写一个字符到文件中去
              fgets 从文件中读取一个字符串
              fputs 写一个字符串到文件中去
              fprintf 往文件中写格式化数据
              fscanf 格式化读取文件中数据
              fread 以二进制形式读取文件中的数据
              fwrite 以二进制形式写数据到文件中去
              getw 以二进制形式读取一个整数
              putw 以二进制形式存贮一个整数
    文件状态检查函数 feof 文件结束
              ferror 文件读/写出错
              clearerr 清除文件错误标志
              ftell 了解文件指针的当前位置
       文件定位函数 rewind 反绕
              fseek 随机定位

文件打开与关闭

文件打开函数原型

FILE *fopen(char *pname,char *mode)

按照mode 规定的方式,打开由pname指定的文件。若找不到由pname指定的相应文件,就按以下方式之一处理:

  • (1) 此时如mode 规定按写方式打开文件,就按由pname指定的名字建立一个新文件;
  • (2) 此时如mode 规定按读方式打开文件,就会产生一个错误。

打开文件的作用

  • (1)分配给打开文件一个FILE 类型的文件结构体变量,并将有关信息填入文件结构体变量;
  • (2)开辟一个缓冲区;
  • (3)调用操作系统提供的打开文件或建立新文件功能,打开或建立指定文件;

FILE *:指出fopen是一个返回文件类型的指针函数;

参数说明

  • pname:是一个字符指针,它将指向要打开或建立的文件的文件名字符串。
  • mode:是一个指向文件处理方式字符串的字符指针。为打开模式。模式可以有r(允许读取),r+(允许读写),w(允许写入),a(允许追加)等
模式描述
r 打开一个已有的文本文件,允许读取文件。
w 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。
a 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。
r+ 打开一个文本文件,允许读写文件。
w+ 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。
a+ 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。

返回值

  • 正常返回:被打开文件的文件指针。
  • 异常返回:NULL,表示打开操作不成功。

说明:C语言将计算机的输入输出设备都看作是文件。例如,键盘文件、屏幕文件等。ANSI C标准规定,在执行程序时系统先自动打开键盘、屏幕、错误三个文件。这三个文件的文件指针分别是:标准输入stdin、标准输出stdout和标准出错 stderr。

文件关闭函数原型

int fclose(FILE *fp);

功能说明

  • 关闭由fp指出的文件。此时调用操作系统提供的文件关闭功能,关闭由fp->fd指出的文件;释放由fp指出的文件类型结构体变量;返回操作结果,即0或EOF。

参数说明

  • fp:一个已打开文件的文件指针。

 返回值

  • 正常返回:0。  
  • 异常返回:EOF(-1),表示文件在关闭时发生错误。

文件的标准打开代码

// C语言文件操作

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

int main(void)
{
    FILE *fp = NULL; // 定义一个文件指针(此时操作位于缓冲区)

    if (NULL == (fp = fopen("aa.txt","r"))) // 判断打开操作是否成功,如果aa.txt不存在的话,此时读操作会出错
    {  
        // fp = fopen("D:\\Programing\\11.txt","r"); // 另一种打开方式 windows中。Linux中采用 “/tmp/test.txt”
        printf("This file cannot be opened.\n");
        exit(1); // 结束程序执行 
    } 
    fclose(fp); 
    
    return 0;
}

文件写入

文件写入函数原型

int fputc(int ch,FILE *fp)

功能说明

  • 把ch中的字符写入由fp指出的文件中去。

参数说明

  • ch:是一个整型变量,内存要写到文件中的字符(C语言中整型量和字符量可以通用)。
  • fp:这是个文件指针,指出要在其中写入字符的文件。

返回值

  • 正常返回: 要写入字符的代码。
  • 非正常返回:返回EOF。例如,要往"读打开"文件中写一个字符时,会发生错误而返回一个EOF。
// C语言文件操作

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

int main(void)
{
    FILE *fp = NULL; // 定义一个文件指针

    if (NULL == (fp = fopen("aa.txt","w"))) // 若要进行文件的写入,此处可以是 r+、w、a 
    {
        printf("This file cannot be opened.\n");
        exit(1); // 结束程序执行 
    } 
    fprintf(fp, "This is a test for fprintf...\n");
    fputs("This is a test for fputs...\n",fp);
    
    fclose(fp);     
    return 0;
}

文件读取

文件读取函数原型

int fgetc(FILE *fp);

功能说明

  • 从fp所指文件中读取一个字符。

参数说明

  • fp:这是个文件指针,它指出要从中读取字符的文件。

返回值

  • 正常返回: 返回读取字符的代码。
  • 非正常返回:返回EOF。例如,要从"写打开"文件中读取一个字符时,会发生错误而返回一个EOF。
// C语言文件读取,并打印输出

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

int main(void)
{
    FILE *fp = NULL; // 定义一个文件指针
    int ch; // 接收文件中字符的ASCII码数值 

    if (NULL == (fp = fopen("aa.txt","r"))) // 判断打开操作是否成功
    {
        printf("This file cannot be opened.\n");
        exit(1); // 结束程序执行 
    } 
    
    ch = fgetc(fp); // 接收ASCII码值,fp指针自动后移一位 
    
    while (ch != EOF)
    {
        putchar(ch);
        ch = fgetc(fp);
    }
    fclose(fp); 
    
    return 0;
}

从流中读取一个字符串:

char *fgets( char *buf, int n, FILE *fp );

函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。

如果这个函数在读取最后一个字符之前就遇到一个换行符 '\n' 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。

也可以使用 int fscanf(FILE *fp, const char *format, ...) 函数来从文件中读取字符串,但是在遇到第一个空格字符时,它会停止读取。

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

int main(void)
{
    FILE *fp = NULL; // 定义一个文件指针
    char buff[200];

    if (NULL == (fp = fopen("aa.txt","r"))) // 若要进行文件的写入,此处可以是 r+、w、a 
    {
        printf("This file cannot be opened.\n");
        exit(1); // 结束程序执行 
    } 
/*    
    fputs("This is a test for fputs...\n",fp);
    fputs("This is a test for fprintf...\n",fp);
*/    
    fscanf(fp, "%s\n", buff);
    printf("1: %s\n", buff);  // 输出 1:This 
    
    fgets(buff, 200, fp);
    printf("2: %s\n", buff); // 输出  2:is a test for fputs...

    fgets(buff, 200, fp);
    printf("3: %s\n", buff); // 输出  3: This is a test for fprintf...
    // 首先,fscanf() 方法只读取了 This,因为它在后边遇到了一个空格。
    // 其次,调用 fgets() 读取剩余的部分,直到行尾。、
    // 最后,调用 fgets() 完整地读取第二行。
    fclose(fp);     
    return 0;
}

对结构体文件的增、删、查操作

函数名: rewind()
功 能 : 将文件内部的位置指针重新指向一个流(数据流/文件)的开头
注意  : 不是文件指针而是文件内部的位置指针,随着对文件的读写文件的位置指针(指向当前读写字节)向后移动。 
        而文件指针是指向整个文件,如果不重新赋值文件指针不会改变。
        rewind函数作用等同于 (void)fseek(stream, 0L, SEEK_SET); 
用 法 : void rewind(FILE *stream);
头文件: stdio.h
清空输入缓冲区操作
通常是为了确保不影响后面的数据读取   
例如在读完一个字符串后紧接着又要读取一个字符,此时应该先执行fflush(stdin);
// Test_File 

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

FILE *fmem;

typedef struct member
{
    char name[16];       // 姓名 
    int id;              // ID
    int phoneNumber;     // 手机号
    char email[64];      // 邮箱 
    char QQ[15];         // QQ 
    char wechat[15];     // 微信 
}members;

members m[100];   // 记录会员信息 
int n=0;         // 会员 

// 输入内容 
void gets_without_newline(char* str)
{
    fgets(str,128,stdin);
    str[strlen(str) - 1] = '\0';
}
// 用于计算文件的行数 
int linecount(FILE *pt)
{
    int x=0;
    char c;
    fscanf(pt,"%c",&c);
    while(!feof(pt))
    {
        if(c=='\n')
            x++;
        fscanf(pt,"%c",&c);
    }
    rewind(pt);             // rewind();函数的功能是 在文件内部指向数据流的开头 
    return x;
}

// 加载会员信息 
int loadMembers()
{
    fmem=fopen("newmembers.txt","r");  // 只读方式打开文件 

    if(fmem!=NULL)
    {
        int x=linecount(fmem);    // 计算文件的行数 
        while (n!=x)
        {
            // %[^,] 表示读取任意字符,以“,”为结尾 
            fscanf(fmem,"%[^,],%d,%d,%s,%s,%s",m[n].name,&m[n].id,&m[n].phoneNumber,m[n].email,m[n].QQ,m[n].wechat);
            fscanf(fmem,"\n");  // 读入一个换行符 
            n++;
        }
        fclose(fmem);
    }
    else
    {
        printf(" 会员信息为空!");
        return 0 ;
    }
    return n;
}

// 添加会员信息 
void addMembers ()
{
    int count,id,flag=0;
    fflush(stdin);   // 清空缓冲区 
    printf("输入会员名字 ");
    gets_without_newline(m[n].name);
    
// 检查该会员是否已经在列表中 
    do
    {flag=0;
        printf("请输入会员 Id: ");
        scanf("%d",&id);
        for (count=0; count<n; count++)
        {
            if(id==m[count].id)
            {
                flag=1;
                break;
            }
        }
    }
    while(flag);

    m[n].id=id;

    fflush(stdin);
    printf("请输入电话号码: ");
    scanf("%d",&m[n].phoneNumber);
    fflush(stdin);
    printf("请输入邮箱地址: ");
    gets_without_newline(m[n].email);
    fflush(stdin);
    printf("请输入QQ号码: ");
    gets_without_newline(m[n].QQ);
    fflush(stdin);
    printf("请输入微信号码: ");
    gets_without_newline(m[n].wechat);
   
    n++;
}

// 移除会员信息 
void remove_member()
{
    int i,j,k,borrowed=0,search,flag=0;

    printf("请输入会员 ID: ");
    scanf("%d",&search);

    for(k=0; k<n; k++) // 第K行退出 
    {
        if(search==m[k].id)
            break;
    }
    
    i=k;
    
    while(i < (n-1))
    {
        m[i]=m[i+1];  // 直接用后面内容覆盖前者 
        i++;
    }

    n=n-1;
}

// 保存会员信息 
void saveMembers()
{
    fmem=fopen("newmembers.txt","w");   // 对文件执行写操作 
    int i;
    for(i=0; i<n; i++)
    {
        fprintf(fmem,"%s,%d,%d,%s,%s,%s",m[i].name,m[i].id,m[i].phoneNumber,m[i].email,m[i].QQ,m[i].wechat);
        fprintf(fmem,"\n");
    }
    fclose(fmem);
}

void DisplayMembers()
{
    int i;
    printf("会员信息: \n");
    for(i=0; i<n; i++)
    {
        printf("%s,%d,%d,%s,%s,%s",m[i].name,m[i].id,m[i].phoneNumber,m[i].email,m[i].QQ,m[i].wechat);
        printf("\n");
    }
}

int main(void)
{
    // 加载必要的文件 
    loadMembers();      // 加载到内存缓冲区 
    DisplayMembers();   // 从缓冲区读取到屏幕 
    addMembers();       // 在缓冲区添加信息 
    remove_member();     
    saveMembers();      // 落盘 

    return 0;
}

RR

posted @ 2019-10-19 15:58  小白的个人总结  阅读(3810)  评论(1编辑  收藏  举报