文本视图和二进制视图
二进制视图:文件每个字节都可以访问。
文本视图:文本+格式字符
fopen(file_path,mode)
函数
模式:
- "r" : 只读
- "w" : 覆写,不存在则创建
- "a" : 追加,不存在则创建
- "r+" : 可读写
- "w+" : 可读写,若存在则覆写,不存在则创建
- "a+" : 可读写,若存在则追加,不存在则创建
示例:文件压缩程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 50
// 摘要程序,3个字符取1个
int main(int argc, char *argv[])
{
FILE *in , *out;
char name[LEN] = "/share/PostLoanData/file.txt"; // 源文件
char target[LEN]; // 目标文件
int ch;
int count = 0;
// 打开文件
if ((in = fopen(name, "r")) == NULL)
{
fprintf(stderr, "open file " %s " fail
", name);
exit(2);
}
// 获得目标文件名
strcpy(target, name);
strcpy(target + strlen(name) - 4, ".red");
printf("压缩文件名: %s
", target);
// 打开目标文件
if ((out = fopen(target, "w")) == NULL)
{
fprintf(stderr, "open file " %s " fail
", target);
exit(3);
}
// 写入文件
while ((ch = getc(in)) != EOF)
{
if (count++ % 3 == 0)
{
putc(ch, out);
}
}
// 关闭流
if (fclose(in) != 0 || fclose(out) !=0 )
{
fprintf(stderr, "error in closing
");
}
puts("Done .
");
return 0;
}
fprintf()文件输入 、 fscanf() 文件输出
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 50
// 摘要程序,3个字符取1个
int main(int argc, char *argv[])
{
FILE *fp;
char name[LEN] = "/share/PostLoanData/file.txt"; // 源文件
char words[LEN];
if ((fp = fopen(name, "a+")) == NULL)
{
fprintf(stdout, "Can't open file " %s " ", name);
exit(1);
}
puts("向文件输入:
");
while (gets(words) != NULL && words[0] != ' ')
fprintf(fp, "%s", words); // 写入文件
puts("打印文件内容:
");
rewind(fp); // 回到文件开始处
while (fscanf(fp, "%s", words) == 1) //读取文件
puts(words);
if (fclose(fp) != 0)fprintf(stderr, "Error closing file
");
puts("Done .
");
return 0;
}
fgets(buf,MAX,fp)读取、fputs(buf,fp)输入
fgets()
函数可以防止存储溢出,与fputs()
一起使用
#include <stdio.h>
#define MAX 50
// 输入输出
int main(int argc, char *argv[])
{
char line[MAX];
while ((fgets(line, MAX, stdin)) != NULL && line[0] != '
')
fputs(line, stdout);
return 0;
}
随机存取 fseek() 、 ftell()
fseek(fp,index,mode)
[文件指针,偏移量,模式]在打开文件中直接移动到任意字节处。移动成功返回0,否则-1。
ftell(fp)
返回long类型文件当前位置。
示例,逆序显示文件
#include <stdio.h>
#include <stdlib.h>
#define SLEN 50
#define CNTL_Z ' 32'
// 反序显示文件
int main(int argc, char *argv[])
{
FILE *fp;
char name[SLEN] = "/share/PostLoanData/file.txt"; // 源文件
char ch;
long count, last;
if ((fp = fopen(name, "rb")) == NULL)
{
printf("open fail %s
", name);
exit(1);
}
fseek(fp, 0L, SEEK_END); // 定位到文件结尾处
last = ftell(fp);
for (count = 1L; count <= last; count++)
{
fseek(fp, -count, SEEK_END); // 回退读取位置
ch = getc(fp);
if (ch != CNTL_Z && ch != '
') putchar(ch);
if (ch == '
') putchar('
');
}
fclose(fp);
return 0;
}
大文件随机读取 fgetpos()
、 gsetpost()
函数
int fgetpos(FILE * restrict stream , fpos_t * restrict pos);
: 调用时在pos位置放置一个fpos_t值,这个值描述文件中一个位置,成功返回0;
int fsetpos(FILE * stream , const fpost_t *pos);
: 调用时,函数使用pos指向的位置上fpos_t
值设定文件指针指向该值所示位置,成功返回0。这个fpos_t
值应该是通过fgetpos()
函数获取。
其他标准I/O函数
int ungetc(int c , FILE *fp) // 将c指定的字符放回输入流。
int fflush(FILE *fp) // 刷新缓冲区
int setvbuf(FILE * restrict fp , char * restrict buf , int mode ,size_t sie) // 建立供标准I/O替换的缓冲区
二进制 I/O fread() 、 fwrite()函数
/** 将二进制数据写入文件 size_t是sizeof运算符返回类型,
ptr为要写入的数据块地址,不确定类型
size表示要写入的数据块大小(字节单位)
nmemb 数据块数目。
fp 要写入的文件
返回成写入的项目数,正常情况与nmemb相等
**/
size_t fwrite(const void * restrict ptr , size_t size , size_t nmemb , FILE * restrict fp);
// 将 256字节大小数据对象写入文件
double buffer[10];
fwrite(buffer,sizeof(double),10,fp);
/** 读取文件 size_t是sizeof运算符返回类型,
ptr 读入文件数据的内存存储地址
size表示要写入的数据块大小(字节单位)
nmemb 数据块数目。
fp 要读取的文件
返回成写入的项目数,正常情况与nmemb相等
**/
size_t fread(void * restrict ptr , size_t size , size_t nmemb , FILE * restrict fp);
// 从文件读取到缓冲区
double buffer[10];
fread(buffer,sizeof(double),10,fp);
int feof(FILE *fp) ; //读取到结尾返回非零值
int ferror(FILE *fp) ; //读写错误返回非零值
示例: 将文件追加到另一个文件
#include <stdio.h>
#include <stdlib.h>
#define SLEN 50
#define BUFSIZE 1024
void appen(FILE *source, FILE *dest);
// 将文件追加到另一个文件
int main(int argc, char *argv[])
{
FILE *fp , *ft;
char source[SLEN] = "/share/PostLoanData/file.txt"; // 源文件
char targe[SLEN] = "/share/PostLoanData/file2.txt"; // 源文件
char ch;
long count, last;
if ((fp = fopen(source, "r")) == NULL)
{
printf("open source fail %s
", source);
exit(1);
}
if ((ft = fopen(targe, "a")) == NULL)
{
printf("open targe fail %s
", targe);
exit(2);
}
if (setvbuf(fp, NULL, _IOFBF, BUFSIZE) != 0) // 替代默认缓冲区
{
fputs("Can't create input buffer
", stderr);
}
appen(fp, ft);
if (ferror(fp) != 0) fprintf(stderr, "Error in read file %s
", source);
if (ferror(ft) != 0) fprintf(stderr, "Error in read file %s
", targe);
fclose(fp);
fclose(ft);
return 0;
}
void appen(FILE * source, FILE * dest)
{
size_t bytes;
static char temp[BUFSIZE]; // 分配一次
while ((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0) // 读取到缓冲区
fwrite(temp, sizeof(char), bytes, dest); // 从缓冲区写入文件
}
随机读取二进制文件
#include <stdio.h>
#include <stdlib.h>
#define ARSIZE 1000
// 随机存取二进制
int main(int argc, char *argv[])
{
double numbers[ARSIZE];
double value ;
FILE *fp;
int i;
const char * file = "/share/PostLoanData/file.dat";
for (i = 0; i < ARSIZE; i++)
numbers[i] = 10.0 * i + 1.0 / (i + 1);
if ((fp = fopen(file, "wb")) == NULL) // 使用写二进制模式打开
{
fprintf(stderr, "Can't open file %s
", file);
exit(1);
}
fwrite(numbers, sizeof(double), ARSIZE, fp); // 写入二进制
fclose(fp);
if ((fp = fopen(file, "rb")) == NULL) // 关闭后用读二进制模式打开
{
fprintf(stderr, "Can't open file %s
", file);
exit(1);
}
printf("从文件中读取第 %d 项
", i = 10);
long pos = (long)i * sizeof(double); // 计算偏移量
fseek(fp, pos, SEEK_SET); // 定位文件开头
fread(&value, sizeof(double), 1, fp); // 读取二进制值
printf("第 %d 项值为 : %f.
", i, value);
fclose(fp);
return 0;
}