文件操作【C语言】

本文详细介绍了C语言中对文件的操作,包括文件的概念、普通文件的打开与关闭、位置指示器的使用,以及文本文件和二进制文件的读写方法。重点讲解了fopen函数的使用模式,如读写、追加等,以及ftell和fseek函数在定位文件位置上的应用。
摘要由CSDN通过智能技术生成

前言

本文记录学习c语言文件操作的过程。


一、文件

什么是文件?

广义:文件就是存储在外设中或由各种外设产生的数据集合
狭义:以外存为载体的描述某种事物的数据集合(普通文件)

广义分类:

  • 普通文件:如:图片、MP3、视频
  • 设备文件:关联某种外设,对该文件的操作就是对该外设的操作。
  • 目录文件:(文件夹)

二、普通文件

普通文件按数据组织形式分为:

  • 二进制文件:数据的原始二进制位进行组织
  • 文本文件:将所有数据转换成可阅读可打印的字符进行存放

文件内容的本质都是二进制。

1.位置指示器

文件内容有多有少,程序读写文件往往都是一小块一小块地逐步读写,文件中每个字节都有一个编号,被称为字节编号或字节位置(不称地址)。

位置指示器:保存当前读写起始位置的一个整型空间。

2.文件的打开与关闭

文件打开函数: fopen

FILE *fopen(const char *__restrict__ _Filename, const char *__restrict__ _Mode)

参数:
   _Filename:带路径的文件名
   _Mode:文件的打开模式,见下表

mode字串打开方式文件不存在文件存在位置指示器
“r”只读失败打开成功,旧内容不变,只读0
“r+”读方式打开,可写失败打开成功,旧内容不变,可读可写0
“w”只覆盖写创建新文件打开成功,清空旧内容,只写0
“w+”覆盖写打开,可读创建新文件打开成功,清空旧内容,可读可写0
“a”追加写创建新文件打开成功,旧内容不变,文件尾追加新内容文件尾
“a+”追加写打开,可读创建新文件打开成功,旧内容不变,文件尾追加新内容并可读开始为0,未写之前随读自动增加,一旦有写操作则到文件尾。

除此以外,“rb”、“rb+”、“wb”、“wb+”、“ab”、“ab+”意味着操作二进制文件。
FILE是一个C库定义好的结构体名,返回值为FILE类型的指针,且位于堆区,意味着fopen函数实现中包含malloc动态分配,因此必须有对应的函数来释放内存。

文件关闭函数:fclose

int fclose(FILE *fp)

关闭成功返回 0 ,失败返回 -1 。文件未关闭会造成:

  • 内存泄漏
  • 数据丢失

文件操作示例:

#include <stdio.h>
int main ()
{
  FILE * pFile;
  //打开文件
  pFile = fopen("myfile.txt","w");//以输出的形式(写)打开文件
  //文件操作
  if (pFile != NULL)  //如果文件打开成功
 {
    fputs ("fopen example",pFile);//以字符串的形式写入
    //关闭文件
    fclose(pFile);
 }
  return 0; 
}

3.位置指示器函数

long ftell(FILE *_File)  // 返回文件指针相对于起始位置的偏移量。
int fseek(FILE *_File, long _Offset, int _Origin)  // 位置指示器定位函数

参数:
   _File:FILE类型地址
   _Offset:位置指示器相对于_Origin偏移量
   _Origin:可填下面三种
     #define SEEK_CUR 1 位置指示器的当前位置
     #define SEEK_END 2 文件尾,_Offset >= 0
     #define SEEK_SET 0 文件头,_Offset <= 0


三、文本文件的读写

1.单个字符的读写

int fgetc(FILE *_File)  // 读取单个字符,成功返回字符ASCII码,失败返回-1
int fputc(int _Ch, FILE *_File)  // 写单个字符,成功返回字符ASCII码,失败返回-1

2.字符串读写

/* 读字符串函数
	功能:功能是从 stream 流中读取 size 个字符存储到字符指针变量 s 所指向的内存空间。
	它的返回值是一个指针,指向字符串中第一个字符的地址。
	参数: 
	_Buf:		代表要保存到的内存空间的首地址,可以是字符数组名,
				也可以是指向字符数组的字符指针变量名。
	_MaxCount:	代表的是读取字符串的长度。
	_File:		表示从何种流中读取,可以是标准输入流 stdin,
				也可以是文件流,即从某个文件中读取,

	标准输入流就是前面讲的输入缓冲区。所以如果是从键盘读取数据的话
	就是从输入缓冲区(标准输入流 stdin)中读取数据,所以第三个参数为 stdin。
*/
char * fgets(char *__restrict__ _Buf, int _MaxCount, FILE *__restrict__ _File)

注意:
1.fgets函数一次最多读一行,其次读size - 1个字符。读取一行字符结束后,会在最后写入一个字符串结束符null。
2.换行符‘ \n ’一起读。

// 写字符串,成功返回写入字符个数,失败返回-1
int fputs(const char *__restrict__ _Str, FILE *__restrict__ _File)

示例:读文件(一行)函数

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

char *MyReadLine(FILE *fp);

void main()
{
    FILE *fp = NULL;
    char *p = NULL;
    fp = fopen("test.txt", "r");
    if (fp == NULL)
        return 1;
    
    p = MyReadLine(fp);
    while (p != NULL)
    {
        printf("%s", p);
        free(p);
        p = MyReadLine(fp);
    }
    fclose(fp);
    system("pause");
    return 0;
}

char *MyReadLine(FILE *fp)
{
    int cur = 0;
    int count = 0;
    int ch = 0;
    char *pout = NULL;
    char *pret = NULL;

    if (fp == NULL)
    {
        printf("Error input");
        return NULL;
    }
    cur = ftell(fp);

    ch = fgetc(fp);
    while(ch != '\n' && ch >= 0)
    {
        count++;
        ch = fgetc(fp);
    }
    count += 2;

    pout = (char *)malloc(count);
    memset(pout, 0, count);

    fseek(fp, cur, SEEK_SET);
    pret = fgets(pout, count, fp);
    if (pret == NULL)
    {
        free(pout);
        return NULL;
    }
    else
    {
        return pout;
    }
}

3.格式化读写

格式化读/写函数 fscanf()和 fprintf(),格式化读/写函数与标准的格式输入/输出函数功能相同,只不过它们的读/写对象不是键盘和显示器,而是文件。fscanf()和 fprintf()函数只适用于 ASCII 码文件的读/写。

// 与printf用法类似,printf往命令行写内容,fprintf往文本文件写
int fprintf(FILE *__restrict__ _File, const char *__restrict__ _Format, ...)
// 类似,从文本文件扫描输入
int fscanf(FILE *__stream, const char *__format, ...)

示例:从文件中读内容,进行处理后存储到另一个文件中。

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

void main()
{
    FILE *fp = NULL;
    char name[20] = "";
    int age = 0;
    float weight = 0;
    float heigh = 0;

    fp = fopen("test1.txt", "r");  // 文件内容:zhangsan 21 78.4 178.8
    if (fp == NULL)
    {
        printf("fopen failed in %s at &d\n", __FILE__, __LINE__);
        return 1;
    }
    fscanf(fp, "%s%d%f%f", name, &age, &weight, &heigh);  // 注意取地址符
    fclose(fp);

    age++;
    weight -= 2;
    heigh += 0.5;

    fp = fopen("test11.txt", "w");
    if (fp == NULL)
    {
        printf("fopen failed in %s at &d\n", __FILE__, __LINE__);
        return 1;
    }
    fprintf(fp, "%s&%d&%.1f&%.1f", name, age, weight, heigh);
    fclose(fp);
    // system("pause");
    return 0;
}

四、二进制文件的读写

/* 读二进制文件函数
参数: 
	_DstBuf:		代表要读到的内存空间的首地址
	_ElementSize:	代表每个元素占多少字节  
	_Count:			期望读取的元素个数
	_File:			要读取的文件
返回值:			
	返回实际读取的元素个数。
*/
size_t fread(void *__restrict__ _DstBuf, size_t _ElementSize, size_t _Count, 
			 FILE *__restrict__ _File)
/* 写二进制文件函数
参数: 
	_Str:		代表要写的内容的首地址
	_Size:		代表每个元素占多少字节  
	_Count:		期望写入的元素个数
	_File:		要写入的文件
返回值:			
	返回写入成功的元素个数。
*/
size_t fwrite(const void *__restrict__ _Str, size_t _Size, size_t _Count, 
			FILE *__restrict__ _File)

示例:bmp文件图片宽在0x12,高在0x16,各占4字节,查询bmp图片的高和宽。

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

void main()
{
    FILE *fp = NULL;
    int w = 0;
    int h = 0;

    fp = fopen("t1.bmp", "rb");
    if (fp == NULL)
        return 1;

    fseek(fp, 18, SEEK_SET);
    fread(&w, sizeof(w), 1, fp);  // 读完之后位置指示器移动到四字节之后
    fread(&h, sizeof(h), 1, fp);
    fclose(fp);

    printf("The width of BMP is %d\n", w);
    printf("The heigh of BMP is %d\n", h);
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值