小端存储
高地址存放高字节
低地址存放低字节
大端储存
低地址存放高字节
高地址存放低字节
文件的打开。
//打开文件
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,但是当你读取的时候,这块地址很有可能不知道是啥了,会导致读取非法地址的错误