一. C 语言文件操作基础

小端存储

高地址存放高字节

低地址存放低字节

大端储存

低地址存放高字节

高地址存放低字节

文件的打开。

    //打开文件
    FILE *fp = fopen("a.txt","r");
    if (fp==NULL) {
        printf("read file error filename = %s\n", "a.txt");
    }

    //关闭文件
    if (fp!=NULL) {
        fclose(fp);
    }

fopen告诉我们三个信息:

1.我们需要打开的文件名

2.使用文件的方式

3.让那个指针变量指向被打开的文件,在本案例中是fp这指针变量

文件有个位置指针。当使用r 和 w 打开的时候,文件指针会在文件的开头。当使用a打开的时候,文件的位置指针会在文件的末尾。

文件的打开有如下几种模式:

文件的关闭

flose(FILE *fp);

只有fopen成功的文件才需要关闭。

关闭文件的原因:

1.释放该文件占用的内存单元

2.防止往文件中写内容时 文件内容不全;关闭文件的动作会触发系统把缓冲区中的数据立即写入到磁盘上。也就是说fflush(FILE *fp)的功能。

文件的读写

1. fputc(char ch, FILE *fp);

int fputc( int ch, FILE *stream );

int putc( int ch, FILE *stream );

写入字符 ch 到给定输出流 stream 。 putc() 可以实现为宏并对 stream 求值超过一次,故对应的参数决不应是有副效应的表达式。

在内部,在写入前将字符转换为 unsigned char 。

参数

ch-要被写入的字符
stream-

输出流

参数

ch-要写入的字符
stream-输出流

返回值

成功时,返回被写入字符。

失败时,返回 EOF 并设置 stream 上的错误指示器(见 ferror() )。

2. fgetc, getc

在标头 <stdio.h> 定义

int fgetc( FILE *stream );

(1)

int getc( FILE *stream );

(2)

1) 从给定的输入流读取下一个字符。

2) 同 fgetc ,除了若 getc 实现为宏,则它可能求值 stream 多于一次,所以实参始终不应为带有副作用的表达式。

stream-读取字符的来源

成功时为作为 unsigned char 获得并转换为 int 的字符,失败时为 EOF 。

若文件尾条件导致失败,则另外设置 stream 上的文件尾指示器(见 feof() )。若某些其他错误导致失败,则设置 stream 上的错误指示器(见 ferror() )。

3 fgets

在标头 <stdio.h> 定义

char *fgets( char          *str, int count, FILE          *stream );

(C99 前)

char *fgets( char *restrict str, int count, FILE *restrict stream );

(C99 起)

从给定文件流读取最多 count - 1 个字符并将它们存储于 str 所指向的字符数组。若文件尾出现或发现换行符则终止分析,后一情况下 str 将包含一个换行符。若读入字节且无错误发生,则紧随写入到 str 的最后一个字符后写入空字符。

参数

str-指向 char 数组元素的指针
count-写入的最大字符数(典型的为 str 的长度)
stream-读取数据来源的文件流

返回值

成功时为 str ,失败时为空指针。

若遇到文件尾条件导致了失败,则设置 stream 上的文件尾指示器(见 feof() )。这仅若它导致未读取字符才是失败,该情况下返回空指针且不改变 str 所指向数组的内容(即不以空字符覆写首字节)。

若某些其他错误导致了失败,则设置 stream 上的错误指示器(见 ferror() )。 str 所指向的数组内容是不确定的(甚至可以不是空终止)。

注解

POSIX 额外要求若 fgets 遇到异于文件尾条件的失败则设置 errno 。

尽管标准规范在 count<=1 的情况下不明,常见的实现

  • 若 count < 1 则不做任何事并报告错误
  • 若 count == 1 ,则
  • 某些实现不做任何事并报告错误,
  • 其他实现不读内容,存储零于 str[0] 并报告成功

4.fputs

在标头 <stdio.h> 定义

int fputs( const char          *str, FILE          *stream );

(C99 前)

int fputs( const char *restrict str, FILE *restrict stream );

(C99 起)

将以NULL结尾的字符串 str 的每个字符写入到输出流 stream ,如同通过重复执行 fputc 。

不将 str 的空字符写入。

参数

str-要写入的空终止字符串
stream-输出流

返回值

成功时,返回非负值。

失败时,返回 EOF 并设置 stream 上的错误指示器(见 ferror )。

注意

相关函数 puts 后附新换行符到输出,而 fputs 写入不修改的字符串。

不同的实现返回不同的非负数:一些返回最后写入的字符,一些返回写入的字符数(或若字符串长于 INT_MAX 则为该值),一些简单地非负常量,例如零。

5.fread

在标头 <stdio.h> 定义

size_t fread( void          *buffer, size_t size, size_t count,
              FILE          *stream );

(C99 前)

size_t fread( void *restrict buffer, size_t size, size_t count,
              FILE *restrict stream );

(C99 起)

从给定输入流 stream 读取至多 count 个对象到数组 buffer 中,如同以对每个对象调用 size 次 fgetc ,并按顺序存储结果到转译为 unsigned char 数组的 buffer 中的相继位置。流的文件位置指示器前进读取的字符数。

若出现错误,则流的文件位置指示器的结果值不确定。若读入部分的元素,则元素值不确定。

参数

buffer-指向要读取的数组中首个对象的指针
size-每个对象的字节大小
count-要读取的对象数
stream-读取来源的输入文件流

返回值

成功读取的对象数,若出现错误或文件尾条件,则可能小于 count

sizecount 为零,则 fread 返回零且不进行其他动作。

fread 不区别文件尾和错误,而调用者必须用 feof 和 ferror 鉴别出现者为何。

示例

#include <stdio.h>
 
enum { SIZE = 5 };
int main(void)
{
    double a[SIZE] = {1.,2.,3.,4.,5.};
    FILE *fp = fopen("test.bin", "wb"); // 必须用二进制模式
    fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组
    fclose(fp);
 
    double b[SIZE];
    fp = fopen("test.bin","rb");
    size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组
    if(ret_code == SIZE) {
        puts("Array read successfully, contents: ");
        for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
        putchar('\n');
    } else { // error handling
       if (feof(fp))
          printf("Error reading test.bin: unexpected end of file\n");
       else if (ferror(fp)) {
           perror("Error reading test.bin");
       }
    }
 
    fclose(fp);
}

输出:

Array read successfully, contents: 
1.000000 2.000000 3.000000 4.000000 5.000000

6.fwrite

在标头 <stdio.h> 定义

size_t fwrite( const void *buffer, size_t size, size_t count,
               FILE *stream );

(C99 前)

size_t fwrite( const void *restrict buffer, size_t size, size_t count,
               FILE *restrict stream );

(C99 起)

count 个来自给定数组 buffer 的对象到输出流stream。如同转译每个对象为 unsigned char 数组,并对每个对象调用 size 次 fputc 以将那些 unsigned char 按顺序写入 stream 一般写入。文件位置指示器前进写入的字节数。

参数

buffer-指向数组中要被写入的首个对象的指针
size-每个对象的大小
count-要被写入的对象数
stream-指向输出流的指针

返回值

成功写入的对象数,若错误发生则可能小于 count

sizecount 为零,则 fwrite 返回零并不进行其他行动。

示例

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
enum { SIZE = 5 };
int main(void)
{
    double a[SIZE] = {1, 2, 3, 4, 5};
    FILE *f1 = fopen("file.bin", "wb");
    assert(f1);
    size_t r1 = fwrite(a, sizeof a[0], SIZE, f1);
    printf("wrote %zu elements out of %d requested\n", r1,  SIZE);
    fclose(f1);
 
    double b[SIZE];
    FILE *f2 = fopen("file.bin", "rb");
    size_t r2 = fread(b, sizeof b[0], SIZE, f2);
    fclose(f2);
    printf("read back: ");
    for(size_t i = 0; i < r2; i++)
        printf("%0.2f ", b[i]);
}

输出:

wrote 5 elements out of 5 requested
read back: 1.00 2.00 3.00 4.00 5.00

7. feof

在标头 <stdio.h> 定义

int feof( FILE *stream );

检查是否已抵达给定文件流的结尾。

参数

stream-要检验的文件流

返回值

若已抵达流尾则为非零值,否则为 ​0​

注意

此函数仅报告最近一次 I/O 操作所报告的流状态,而不检验关联的数据源。例如,若最近一次 I/O 是抵达文件最后字节的 fgetc ,则 feof 返回零。下个 fgetc 失败并更改流状态为文件尾。然后 feof 才返回非零。

典型用法中,输入流处理在任何错误时停止;而 feof 和 ferror 用于区别不同错误条件。

示例

#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    FILE* fp = fopen("test.txt", "r");
    if(!fp) {
        perror("File opening failed");
        return EXIT_FAILURE;
    }
 
    int c; // 注意:int,非char,要求处理EOF
    while ((c = fgetc(fp)) != EOF) { // 标准C I/O读取文件循环
       putchar(c);
    }
 
    if (ferror(fp))
        puts("I/O error when reading");
    else if (feof(fp))
        puts("End of file reached successfully");
 
    fclose(fp);
}

主要用到的函数一览

网络游戏升级的一些应用

第二行一般是版本号,当前要升级的版本是6。假设user 本地的版本是4,那么就会下载倒数第二行和倒数第一行。让user 下载,然后安装

0D 0A对应 换行 回车

坑点

注意的是:如果有指针要存储在本地文件中,要特别注意,因为指针里面存储的地址,是运行时的,也就是说:假设当你存储的时候,当时的地址是0XAABB11,但是当你读取的时候,这块地址很有可能不知道是啥了,会导致读取非法地址的错误

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值