小端存储
高地址存放高字节
低地址存放低字节
大端储存
低地址存放高字节
高地址存放低字节
文件的打开。
//打开文件
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
| 在标头 | ||
| 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
| 在标头 | ||
| 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
| 在标头 | ||
| 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
| 在标头 | ||
| size_t fread( void *buffer, size_t size, size_t count, | (C99 前) | |
| size_t fread( void *restrict buffer, size_t size, size_t count, | (C99 起) | |
从给定输入流 stream 读取至多 count 个对象到数组 buffer 中,如同以对每个对象调用 size 次 fgetc ,并按顺序存储结果到转译为 unsigned char 数组的 buffer 中的相继位置。流的文件位置指示器前进读取的字符数。
若出现错误,则流的文件位置指示器的结果值不确定。若读入部分的元素,则元素值不确定。
参数
| buffer | - | 指向要读取的数组中首个对象的指针 |
| size | - | 每个对象的字节大小 |
| count | - | 要读取的对象数 |
| stream | - | 读取来源的输入文件流 |
返回值
成功读取的对象数,若出现错误或文件尾条件,则可能小于 count 。
若 size 或 count 为零,则 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
| 在标头 | ||
| size_t fwrite( const void *buffer, size_t size, size_t count, | (C99 前) | |
| size_t fwrite( const void *restrict buffer, size_t size, size_t count, | (C99 起) | |
写 count 个来自给定数组 buffer 的对象到输出流stream。如同转译每个对象为 unsigned char 数组,并对每个对象调用 size 次 fputc 以将那些 unsigned char 按顺序写入 stream 一般写入。文件位置指示器前进写入的字节数。
参数
| buffer | - | 指向数组中要被写入的首个对象的指针 |
| size | - | 每个对象的大小 |
| count | - | 要被写入的对象数 |
| stream | - | 指向输出流的指针 |
返回值
成功写入的对象数,若错误发生则可能小于 count 。
若 size 或 count 为零,则 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
| 在标头 | ||
| 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,但是当你读取的时候,这块地址很有可能不知道是啥了,会导致读取非法地址的错误
本文介绍了计算机中的字节序概念,包括小端存储和大端存储的工作原理。同时,详细讲解了文件的打开和关闭过程,强调了文件指针的重要性和不同打开模式的影响。接着,重点讨论了文件的读写操作,如fopen、fclose、fputc、fgetc、fgets、fputs、fread、fwrite等函数的使用,并给出了相关示例。此外,还提到了feof和ferror函数在错误处理中的作用。最后,文章提醒在处理指针存储时需要注意运行时地址变化可能导致的问题。

被折叠的 条评论
为什么被折叠?



