C语言提高(三)

九 文件操作
1文件分类
1)按逻辑结构
a) 记录文件:由具有一定结构的记录组成(定长和不定长)
b) 流式文件:由一个个字符(字节)数据顺序组成
2) 按存储介质
a)普通文件:存储介质文件(磁盘、磁带等)
b)设备文件:非存储介质(键盘、显示器、打印机等)
3)按组织形式
a)文本文件:ASCII文件,每个字节存放一个字符的ASCII码
b)二进制文件:数据按其在内存中的存储形式原样存放

2 标准文件的读写
1) fopen(char *filename,char *type);//返回文件句柄FILE
参数type :

"r"             打开,只读 
"w"             打开,文件指针指到头,只写 
"a"             打开,指向文件尾,在已存在文件中追加 
"rb"            打开一个二进制文件,只读 
"wb"            打开一个二进制文件,只写 
"ab"            打开一个二进制文件,进行追加 
"r+"            以读/写方式打开一个已存在的文件 
"w+"            以读/写方式建立一个新的文本文件 
"a+"            以读/写方式打开一个文件文件进行追加 
"rb+"           以读/写方式打开一个二进制文件 
"wb+"           以读/写方式建立一个新的二进制文件 
"ab+"           以读/写方式打开一个二进制文件进行追加 

int fclose(FILE *stream);

当用fopen()成功的打开一个文件时,该函数将返回一个FILE指针,如果文件打开失败,将返回一个NULL指针。如想打开test文件,进行写:

FILE *fp;
if((fp=fopen("test","w"))==NULL)
{
    printf("File cannot be    opened\n");
    exit();
}
else
printf("File opened for writing\n");
fclose(fp);

3 非标准文件的读写
这类函数最早用于UNIX操作系统,ANSI标准未定义,但有时也经常用到。

1).文件的打开和关闭
open()函数的作用是打开文件,其调用格式为:int open(char *filename, int access);
access:
O_RDONLY 只读 O_APPEND 文件指针指向末尾
O_WRONLY 只写 O_CREAT 文件不存在时创建文件, 属性按基本模式属性
O_RDWR 读写 O_TRUNC 若文件存在, 将其长度缩为0, 属性不变
O_BINARY 打开一个二进制文件
O_TEXT 打开一个文字文件

open()函数打开成功, 返回值就是文件描述字的值(非负值), 否则返回-1。
close()函数的作用是关闭由open()函数打开的文件, 其调用格式为:
int close(int fd);
该函数关闭文件描述字fd相连的文件。
2)读写文件

int read(int handle, void *buf, int count);

read()函数从handle(文件描述字)相连的文件中, 读取count个字节放到buf所指的缓冲区中,返回值为实际所读字节数, 返回-1表示出错。返回0 表示文件结束。
write()函数的调用格式为:

int write(int handle, void *buf, int count);

write()函数把count个字节从buf指向的缓冲区写入与handle相连的文件中, 返回值为实际写入的字节数。

3)随机定位函数
lseek()函数的调用格式为:

           int lseek(int handle, long offset, int fromwhere);

该函数对与handle相连的文件位置指针进行定位,功能和用法与fseek()函数相同。
tell()函数的调用格式为:

               long tell(int handle);

该函数返回与handle相连的文件现生位置指针, 功能和用法与ftell()相同

4 标准文件操作API
1) fgetc fputc 按照字符读写文件

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

void main01_fputc()
{
int     i = 0;
FILE *fp = NULL;
//char *filename = "c:\\1.txt";
char *filename2 = "c:/2.txt";  // 统一的用45度 
char a[27]= "abcdefghijklmn";
fp = fopen(filename2, "r+");
if (fp == NULL)
{
    printf("func fopen() err:%d \n");
    return;
}
printf("打开成功\n");
for (i=0; i<strlen(a); i++)
{
    fputc(a[i], fp);
}
fclose(fp);
return ;
}

void main02_fgetc()
{
int     i = 0;
FILE *fp = NULL;
//char *filename = "c:\\1.txt";
char *filename2 = "c:/2.txt";  // 统一的用45度 
char a[27]= "abcdefghijklmn";
fp = fopen(filename2, "r+"); //读和写方式
if (fp == NULL)
{
    printf("func fopen() err:%d \n");
    return;
}
printf("打开成功\n");
while (!feof(fp))//检查是否到文件末尾
{
    char tempc = fgetc(fp);
    printf("%c", tempc);
}
if (fp != NULL)
{
    fclose(fp);
}
return ;
}

void main()
{
main01_fputc();//写
main02_fgetc();//读
printf("hello...\n");
system("pause");
return ;
}

2)fputs fgets 按照行(字符串)读写文件(读写配置文件)

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

void main21_fputs()
{
int i = 0;
FILE *fp = NULL;
//char *filename = "c:\\1.txt";
char *filename2 = "c:/22.txt";  // 统一的用45度 
char a[27]= "abcdefghijklmn";
//fp = fopen(filename2, "r+");   //读写的方式 打开文件 如果文件不存在 则报错
fp = fopen(filename2, "w+");     //读写的方式 创建文件
if (fp == NULL)
{
    printf("func fopen() err:%d \n");
    return;
}
printf("打开成功\n");

fputs(a, fp);
fclose(fp);

return ;
}

void main22_fgets()
{
int  i = 0;
FILE *fp = NULL;
//char *filename = "c:\\1.txt";
char *filename2 = "c:/22.txt";  // 统一的用45度 
//char a[27]= "abcdefghijklmn";
char buf[1024];
fp = fopen(filename2, "r+"); //读和写方式
if (fp == NULL)
{
    printf("func fopen() err:%d \n");
    return;
}
printf("打开成功\n");

//1 //C 函数库 会 一行一行的copy数据 到buf指针所指的内存空间中 并且变成C风格的字符串
//2 把\n也copy到我们的buf中
//3 内存打包 (把内存首地址 + 内存的长度)
while (!feof(fp))
{
    //_Check_return_opt_ _CRTIMP char * __cdecl fgets(_Out_z_cap_(_MaxCount) char * _Buf, _In_ int _MaxCount, _Inout_ FILE * _File);
    char *p = fgets(buf, 1024, fp);  //C 函数库 会 一行一行的copy数据 到buf指针所指的内存空间中 并且变成C风格的字符串
    if (p == NULL)
    {
        goto End;
    }   
    printf("%s", buf);
}
End:
if (fp != NULL)
{
    fclose(fp);
}
return ;
}

void main()
{
//main21_fputs();
main22_fgets();
printf("hello...\n");
system("pause");
return ;
}

3)fread fwirte 按照块读写文件(大数据块迁移)

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

//直接把内存数据 写入到 文件中
typedef struct Teacher
{
char name[64];
int age ;
}Teacher;

void main_fwrite()
{
int i = 0;
FILE *fp = NULL;
char *fileName = "c:/3.data";
Teacher tArray[3];
int  myN = 0;

for (i=0; i<3; i++)
{
    sprintf(tArray[i].name, "%d%d%d", i+1, i+1, i+1);
    tArray[i].age = i + 31;
}

fp = fopen(fileName, "wb");
if (fp == NULL)
{
    printf("建立文件失败\n");
    return ;
}
for (i=0; i<3; i++)
{
    //_Check_return_opt_ _CRTIMP size_t __cdecl 
    //  fwrite(_In_count_x_(_Size*_Count) const void * _Str, _In_ size_t _Size, _In_ size_t _Count, _Inout_ FILE * _File);
    //函数参数
    //_Str : 从内存块的开始
    //_Size  //内存打包技术
    //_Count 写多少次
    //_File : 写入到 文件指针 所指向的文件中

    //函数的返回值 
    myN = fwrite( &tArray[i],sizeof(Teacher) , 1, fp);

    //myN 判断 有没有写满  磁盘

}

if (fp != NULL)
{
    fclose(fp);
}
}

void main_fread()
{
int i = 0;
FILE *fp = NULL;
char *fileName = "c:/3.data";
Teacher tArray[3];
int  myN = 0;

fp = fopen(fileName, "r+b");
if (fp == NULL)
{
    printf("建立文件失败\n");
    return ;
}
for (i=0; i<3; i++)
{
    //_Check_return_opt_ _CRTIMP size_t __cdecl 
    // fread(_Out_bytecap_x_(_ElementSize*_Count) void * _DstBuf, _In_ size_t _ElementSize, _In_ size_t _Count, _Inout_ FILE * _File);
    myN  = fread(&tArray[i], sizeof(Teacher), 1, fp);
}

for (i=0; i<3; i++)
{
    //sprintf(tArray[i].name, "%d%d%d", i+1, i+1, i+1);
    //tArray[i].age = i + 31;
    printf("name:%s, age:%d \n", tArray[i].name, tArray[i].age);
}

if (fp != NULL)
{
    fclose(fp);
}
}

void main()
{
main_fwrite();
main_fread();
printf("hello...\n");
system("pause");
return ;
}

4)文件控制api
int fseek(FILE *stream, long offset, int fromwhere);函数设置文件指针stream的位置。函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere(偏移起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。
fseek函数和lseek函数类似,但lseek返回的是一个off_t数值,而fseek返回的是一个整型。

long ftell(FILE *stream);用于得到文件位置指针当前位置相对于文件首的偏移字节数。 利用函数 ftell() 也能方便地知道一个文件的长。
如以下语句序列: fseek(fp, 0L,SEEK_END); len =ftell(fp);

5) 清除文件缓冲区函数:int fflush(FILE *stream);
fflush()函数将清除由stream指向的文件缓冲区里的内容,常用于写完一些数据后,立即用该函数清除缓冲区,以免误操作时,破坏原来的数据。

6)设置文件缓冲区函数

 void setbuf(FILE *stream,char *buf);
 void setvbuf(FILE *stream,char *buf,int type,unsigned size);

猜你喜欢

转载自blog.csdn.net/weixin_40878579/article/details/81270998