C语言的文件操作指南,掌握这些函数就够了!

C语言文件操作
文件是存输数据的介质。
文件名
一个文件要有一个唯一的文件标识,以便用户识别和引用。 
文件名 包含 3 部分: 文件路径 + 文件名主干 + 文件后缀
例如: c:\code\test.txt
      c:\code 文件路径  test 文件名主干 .txt 文件后缀
为了方便起见,文件标识常被称为 文件名
文件类型
根据数据的形式, 数据文件 被分为 文本文件 二进制文件
数据在内存中以二进制形式存储,如果不加转换,直接存放到外存(文件),就是 二进制文件
如果转换成 ASCII字符 再存储到文件中,就是 文本文件
文件属于外存,磁盘是外存的一部分
一个数据在内存中是怎么存储的呢?
字符一律以 ASCII码值 形式存储,数值型数据既可以用 ASCII 形式存储,也可以使用二进制形式存储。
将整数 10000输出到磁盘是什么情况呢?
如有整数 10000 ,如果以 ASCII字符 的形式输出到磁盘,则磁盘中占用 5 个字节(每个字符一个字节) --------文本文件存储 ,而
二进制形式输出,则在磁盘上只占 4 个字节( VS2013 测试) ------------二进制文件存储
文件指针
缓冲文件系统中,关键的概念是 文件类型指针 ,简称 文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名
字,文件状态及文件当前的位置等)。
这些信息是保存在一个结构体变量中的。该结构体类型是由系统 声明的,取名 FILE .
文件信息区
文件test.txt的相关信息
以上的这块内存对应的是一个FILE类型的变量。
FILE类型是系统声明的一种结构体类型。
struct _iobuf {
        char * _ptr ;
        int   _cnt ;
        char * _base ;
        int   _flag ;
        int   _file ;
        int   _charbuf ;
        int   _bufsiz ;
        char * _tmpfname ;
      };
typedef struct _iobuf FILE
不同的 C 编译器的 FILE 类型包含的内容不完全相同,但是大同小异。
每当打开一个文件的时候,系统会根据文件的情况自动创建一个 FILE 结构的变量,并填充其中的信息,
使用者不必关心细节。
一般都是通过一个 FILE 的指针来维护这个 FILE 结构的变量,这样使用起来更加方便。
下面我们可以创建一个 FILE* 的指针变量 :                FILE*  pf ;
定义 pf 是一个指向 FILE 类型数据的指针变量。使 pf 指向某个文件的文件信息区(是一个结构体变
量)。通过该文件信息区中的信息就能够访问该文件。也就是说, 通过文件指针变量能够找到与它关联
的文件
文件的打开和关闭
文件在读写之前应该先 打开文件 ,在使用结束之后应该 关闭文件
在编写程序的时候,在打开文件的同时,都会返回一个 FILE* 的指针变量指向该文件,也相当于建立了指
针和文件的关系。
ANSIC 规定使用 fopen 函数来打开文件, fclose 来关闭文件。
打开方式如下
                         FILE* fopen ( const char* filename,const char* mode); // 传入文件名时,实际上传入的是字符串,也就是首字符的地址; mode 表示打开的方式,也是传入字符串,也是首字符的地址,返回类型是一个 FILE* 指针 (文件指针) ,打开文件成功返回 正常指针, 打开失败返回 NULL空指针
                        int fclose (FILE* stream ); //输入文件指针作为实参,完成文件关闭操作
int main()
{
    //打开文件test.txt
  fopen( "C:\\2020_code\\test_5_6\\test.txt" ,"r"); //直接传入绝对路径,多加\防止被识别为转义字符
     fopen( "test.txt" ,"r");//直接传入 相对路径 ,只有在test.txt,在 当前路径 下才可这么写,即正在录入的c文件,与test.txt 在同一层文件夹
    fopen(" ../ test.txt","r");
     fopen(" ../../ test.txt","r"); 表示test上一级路径的上一级路径
//   ..  表示上一级路径
//   .   表示当前路径
    FILE* pf = fopen ("test.txt", "r"); //打开后返回一个指针,需要用指针来接收一下
    使用fopen函数后,会立刻给test.txt创建一个文件信息区
test.txt的文件信息区  本质上是FILE结构的结构体变量
返回的就是该结构体的起始地址
如果打开失败,则连 结构体 都不会创建
文件test.txt的相关信息
    if ( pf==NULL)
{
    printf("%s\n",strerror(errno)); //解释报错原因
    return 0;
}
    //打开成功
   //读文件
   ...........................................
   //关闭文件
fclose( pf );
pf=NULL;
return 0;
}
int main()
{
    //打开文件
    FILE * pf = fopen( "D:\\QQ\\test.txt" , "r" ); // 假如选择 "w" 只写 ,若选择打开的文件不存在,就会自动生成一个该文件
    if (pf == NULL )
    {
        printf( "%s\n" , strerror( errno ));
        return 0;
    }
    fclose(pf);
    pf = NULL ;
    return 0;
}
只写 "w" 的情况下,如果文件没有创建,会直接以该文件名,创建一个新文件
写 “w" 的形式 ,会将原来文件的内容清空,然后从开头开始写入
追加 " a " 的形式,会在原来文件内容的后面继续写入
文件的顺序读写
int main()
{
    FILE * pfwrite = fopen( "D:\\QQ\\test.txt" , "w" );
    if (pfwrite == NULL )
    {
    printf( "%s\n" , strerror( errno )); //strerror(errno) 以字符串的形式解释错误,并返回字符串地址
        return 0;
    }
    //写文件
    fputc( 'b' , pfwrite);
    fputc( 'i' , pfwrite);
    fputc( 't' , pfwrite);
    //关闭文件
    fclose(pfwrite);
    pfwrite = NULL ;
    return 0;
}
int main()
{
    FILE * pfRead = fopen( "D:\\QQ\\test.txt" , "r" );// “r”表明了 文件将会作为文件输出流 来进行操作
    if (pfRead == NULL )
    {
        printf( "%s\n" , strerror( errno )); //strerror(errno) 以字符串的形式解释错误,并返回字符串
        return 0;
    }
    //读文件
    printf( "%c" , fgetc(pfRead)); //fgetc() 括号内输入 文件指针 便可 从头往后读取字符
    printf( "%c" , fgetc(pfRead));
    printf( "%c" , fgetc(pfRead));
    //关闭文件
    fclose(pfRead);
    pfRead = NULL ;
    return 0;
}
写内容到文件里去----------文件输入流
从文件中读取内容----------文件输出流
键盘----------标准输入设备--------stdin
                                               是一个程序默认打开的两个流设备
屏幕----------标准输出设备--------stdout
只要程序运行起来就会默认打开三个流    stdin     stdout   stderr  类型为 FILE*
fgetc使用于所有流,其中包括标准输入,输出流
int main()
{
    int ch=fgetc(stdin); //输入字符 h 
    fputc(ch,stdout); //会把 h 打印到屏幕上
return 0;
}

fgetc  读取一个字符 (读取一个后会自动来到下一个字符)

int fgetc ( FILE * stream ); 从文件中读取一个字符,并返回字符的ASCII码值,实参为文件指针,或者标准输入流,stdin 键盘
从流中获取字符
返回指定 流的内部文件位置指示器当前所指向的字符。然后,内部文件位置指示器将前进到下一个字符。
如果调用流时位于文件末尾,则该函数返回  EOF 并设置流 ( feof)  的文件结束指示符
如果发生读取错误,该函数将返回  EOF 并设置流( ferror) 的错误指示器
fgetc 和  getc 是等效的,只是  getc 在某些库中可以作为宏实现。

参数

指向标识输入流的 FILE 对象的指针。

返回值

成功后,将返回读取的字符(提升为 int 值)。即返回字符的ASCII码值

fputc   输入一个字符

int fputc ( int character, FILE * stream );   可以输入字符,也可以输入字符的ASCII码值,向流输出成功后,会返回字符的ASCII码值,流,包括文件指针流,实参为文件指针,和标准输出流,stdout 即屏幕
Write character to stream
Writes a  character to the  stream and advances the position indicator.
The character is written at the position indicated by the  internal position indicator of the  stream, which is then automatically advanced by one.

Parameters

character

The int promotion of the character to be written.

The value is internally converted to an unsigned char when written.

stream

Pointer to a FILE object that identifies an output stream.

Return Value

On success, the  character written is returned.  输入成功返回字符的ASCII码值
fgets  每次读取文件的一行,再次读取会自动读取下一行, 适用于所有流
fgets
char * fgets ( char * str, int num, FILE * stream );    str是数据的起始存储位置,即从str指向的地址开始存储,一般就是字符数组首元素的地址, num是最多可存放多少个字符,这由字符数组大小决定
Get string from stream
Reads characters from  stream and stores them as a C string into  str until ( num-1) characters have been read or either a newline or the  end-of-file is reached, whichever happens first.
A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to  str.

Parameters

str

Pointer to an array of chars where the string read is copied.

num

Maximum number of characters to be copied into str (including the terminating null-character).

fputs  写一个字符串到流里面去 

fputs

int fputs ( const char * str, FILE * stream );  (  传入字符串,流  )  (“hello,world”,pf)也可直接传入字符数组首元素的地址 ( arr ,流 )流包括文件输入流,和标准输出流
Write string to stream
Writes the  C string pointed by  str to the  stream.
The function begins copying from the address specified ( str) until it reaches the terminating null character ('\0'). This terminating null-character is not copied to the stream.
Notice that fputs not only differs from  puts in that the destination  stream can be specified, but also fputs does not write additional characters, while  puts appends a newline character at the end automatically.

Parameters

str

C string with the content to be written to stream.

stream

Pointer to a FILE object that identifies an output stream.

格式化的输出输入
格式化的输出 ,意思就是,你想以什么样的格式输出,就自己定好,输出进去便可
struct S
{
    int n;
    float score;
    char arr[10];
};
int main()      3.14f 表示是float类型,防止被默认为double
{
    struct S s={100,3.14f,"bit"};
    FILE* pf=fopen("test.txt","w");
    if(pf==NULL)
    {
        return 0;
    }
//格式化的形式写文件
fprintf ( pf ,"%d %f %s ",s.n,s.score,s.arr);想写啥类型的数据,自己在括号里定好    fprintf 可以把一长串字符串输入到文件里面去
fclose(pf);
pf=NULL;
return 0;
}

printf

int printf ( const char * format, ... );
Print formatted data to stdout    针对标准输出流

fprintf

int fprintf ( FILE * stream, const char * format, ... );    针对流
Write formatted data to stream
Writes the C string pointed by  format to the  stream. If  format includes  format specifiers (subsequences beginning with %), the additional arguments following  format are formatted and inserted in the resulting string replacing their respective specifiers.
After the  format parameter, the function expects at least as many additional arguments as specified by  format.

Parameters

stream

Pointer to a FILE object that identifies an output stream.

格式化的输入
struct S
{
    int n;
    float score;
    char arr[10];
};
int main()     
{
    struct S s={0}; //表示未初始化
    FILE* pf=fopen("test.txt","w");
    if(pf==NULL)
    {
         return 0;
    }
//格式化的形式读文件
//格式化的输入数据
fscanf(pf,"%d %f %s ",&(s.n),&(s.score),s.arr);//取结构体变量的地址,可以直接用 s.n 访问结构体变量,然后直接 &(s.n)取其地址
printf( "%d %f %s ",s.n,s.score,s.arr);
fclose(pf);
pf=NULL;
return 0;
}

scanf

int scanf ( const char * format, ... );

fscanf

int fscanf ( FILE * stream, const char * format, ... );
Read formatted data from stream
Reads data from the  stream and stores them according to the parameter  format into the locations pointed by the additional arguments.
The additional arguments should point to already allocated objects of the type specified by their corresponding format specifier within the  format string.

Parameters

stream

Pointer to a FILE object that identifies the input stream to read data from.

scanf/printf 是针对标准输入流/标准输出流的格式化输入/输出语句
fscanf/fprintf 是针对所有输入流/所有输出流的格式化输入输出语句
sscanf / sprintf  是从字符串中读取格式化的数据/把格式化的数据存储到字符串

sscanf  从一个字符串中拿出一个格式化的数据    s表示字符串操作

int sscanf ( const char * s, const char * format, ...);         (字符串起始地址,格式,地址........)
Read formatted data from string

sprintf  把格式化的数据写到一个字符串里面去

int sprintf ( char * str, const char * format, ... );       ( 字符串起始地址, 格式 数据.........)
Write formatted data to string
struct S
{
    int n;
    float score;
    char arr[10];
};
int main()
{
    struct S s = { 100,3.14f, "abcdef" }; //能不能将结构体里存的数据转化成一个字符串
    struct S temp = {0};
    char buf[1024] = { 0 }; //结构体里的数据,就是我们所说的格式化的数据
    //把格式化的数据存储到 buf
    sprintf(buf, "%d %f %s" , s.n, s.score, s.arr); // s.arr 表示访问数组
   // printf( "%s\n" , buf);
  //从buf中读取格式化的数据到tmp结构体中
    sscanf(buf, "%d %f %s",&(tmp.n),&(tmp.score),tmp.arr);
    return 0;
}
打印结果为  100 3.140000 abcdef   这里打印时,就已经是在打印字符串了
二进制的输入和输出
二进制输出 fwrite  写  输出指向文件输出

fwrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );         ( ptr 当前存储数据的位置 , 元素的字节大小 , 最多写入多少个 , 指针指向的文件结构  ) ,最多写入多少个由文件大小决定
Write block of data to stream
struct S
{
    char name[20];
    int age;
    double score;
};
 int main()
{
    struct S s = { "张三",20,55.6 };
    FILE* pf = fopen("D:\\QQ\\test.txt", "wb");  //以二进制形式写,用wb
    if (pf == NULL)
    {
       return 0;
    }
    //二进制的形式写文件
    fwrite(&s, sizeof(struct S), 1, pf);
    fclose(pf);
    pf = NULL;
    return 0;
}
二进制输入 fread   读  输入指向外界输入

fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );              (   ptr 拿出的数据应该存放的位置 , 元素的大小 , 最多读取多少个 , 指针指向的文件结构 )   ptr用于存储数据的位置也可以是数组,数组的大小决定了最多可以读取多少个   返回值类型 size_t 其实就是返回整型数值,该数值是成功读取的元素个数
Read block of data from stream
int main()
{
    struct S tmp = { 0 };
    FILE * pf = fopen( "D:\\QQ\\test.txt" , "rb" );  //以二进制形式读,用rb
    if (pf == NULL )
    {
        return 0;
    }
    //二进制的形式读文件
    fread(&tmp, sizeof ( struct S ), 1, pf);//以二进制的形式读出数据
    printf( "%s %d %lf\n" , tmp.name, tmp.age, tmp.score);//输出到屏幕上,电脑自然能读懂二进制
    fclose(pf);
    pf = NULL ;
    return 0;
}
数据库
MySQL
..........................
文件存放数据    1.不安全
                        2.大量数据,不高效
                        C语言操作 MySQL 数据库
下面这个非常重要,以后常会用到
         文件的随机读取      fseek  根据文件指针的位置和偏移量来定位文件指针 
 解释一下: 文件里面存放了, a  b  c   d   e   f   上来我就要从e开始读取  以上的函数显然是做不到的
a  b  c  d  e  f   刚打开时,文件指针默认指向开始位置

fseek

int fseek ( FILE * stream, long int offset, int origin );    (  文件指针  , 偏移量  ,文件指针的设定位置 )     若起始位置在 a  选择偏移量为 2 则文件指针会被移动到  c  ,当然偏移量可以为负
Move the file pointer to a specified  location 移动文件指针到特定的地方
origin 是说明从什么位置开始定位指针    SEEK_END 末尾处
Constant
Reference position
SEEK_SET
Beginning of file起始位置
SEEK_CUR
Current position of the file pointer当前位置
SEEK_END
End of file *末尾位置
SEEK_END 需注意,abcdef 的末尾在 f 的后面,是空白处 
int main()
{
    FILE * pf = fopen( "D:\\QQ\\test.txt" , "r" );
    if (pf == NULL )
    {
        return 0;
    }
    //1.定位文件指针
    fseek(pf, 2, SEEK_CUR ); //文件指针从当前位置,偏移两个位置,拿到字符 c
    //2.读取文件
    int ch = fgetc(pf);
    printf( "%c\n" , ch);
    fclose(pf);
    pf = NULL ;
    return 0;
}
    
 ftell    返回文件指针相对于起始位置的偏移量

ftell

 int ftell ( FILE * stream );     (  文件指针  )
Get current position in stream
int main()
{
    FILE * pf = fopen( "D:\\QQ\\test.txt" , "r" );
    if (pf == NULL )
    {
        return 0;
    }
    //1.定位文件指针
    //fseek(pf, 2, SEEK_CUR);//文件指针从当前位置,偏移两个位置,拿到字符 c
    fgetc(pf); //fgetc()函数会带着文件指针往后移动,文件指针指向哪个字符,fgetc就会去获取哪个字符
    int pos = ftell(pf);
    printf( "%d\n" , pos);  //打印结果为 1
    fclose(pf);
    pf = NULL ;
    return 0;
}
rewind     让文件指针回到文件的起始位置    rewind的英文意思为转回
 int main()
{
    FILE * pf = fopen( "D:\\QQ\\test.txt" , "r" );
    if (pf == NULL )
    {
        return 0;
    }
    //1.定位文件指针
    //fseek(pf, 2, SEEK_CUR);//文件指针从当前位置,偏移两个位置,拿到字符 c
    fgetc(pf); //fgetc()函数会带着文件指针往后移动
    rewind(pf); 
    int pos = ftell(pf);
    printf( "%d\n" , pos);  //打印结果为 0
    fclose(pf);
    pf = NULL ;
    return 0;
}
文件结束判定
被错误使用的   feof
牢记:在文件读取过程中,不能用 feof 函数的返回值直接用来判断文件是否结束。
而是 应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束
简单来说 feof 是用来告诉我们 ,什么原因导致了文件读取的结束
1. 文本文件读取是否结束,判断返回值是否为 EOF fgetc ),或者 NULL fgets
例如:
    fgetc 判断是否为 EOF .  读取字符时
    fgets 判断返回值是否为 NULL .
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
        fread 判断返回值是否小于实际要读的个数。 fread返回值是成功读取的个数
函数 perror ---  直接打印 标注:对应的错误信息
int main()
{
    //strerror   ---  把错误码对应的错误信息的字符串地址返回,需要引用 头文件 < errno.h >
    //printf("%s/n", strerror(errno));
    //perror     ---  直接打印 标注:对应的错误信息
    FILE * pf = fopen( "tests.txt" , "r" );
    if (pf == NULL )
    {
        perror( "hehe" ); //  打印结果为 hehe: No such file or directory
        return 0;
    }
    //读文件
    //关闭文件
    fclose(pf);
    pf = NULL ;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值