C - 基础 - 文件输入、输出

文本视图和二进制视图

二进制视图:文件每个字节都可以访问。 文本视图:文本+格式字符

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 \n ", name);
        exit(2);
    }

    // 获得目标文件名
    strcpy(target, name);
    strcpy(target + strlen(name) - 4, ".red");

    printf("压缩文件名: %s \n", target);

    // 打开目标文件
    if ((out = fopen(target, "w")) == NULL)
    {
        fprintf(stderr, "open file \" %s \" fail \n ", 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 \n");
    }
    puts("Done .\n");
    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("向文件输入:\n");
    while (gets(words) != NULL && words[0] != '\0')
        fprintf(fp, "%s", words);   // 写入文件

    puts("打印文件内容:\n");
    rewind(fp);     // 回到文件开始处
    while (fscanf(fp, "%s", words) == 1)    //读取文件
        puts(words);

    if (fclose(fp) != 0)fprintf(stderr, "Error closing file \n");
    puts("Done .\n");
    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] != '\n')
        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 '\032'

// 反序显示文件
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\n", 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 != '\r') putchar(ch);
        if (ch == '\r') putchar('\n');
    }
    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\n", source);
        exit(1);
    }

    if ((ft = fopen(targe, "a")) == NULL)
    {
        printf("open targe fail %s\n", targe);
        exit(2);
    }
    if (setvbuf(fp, NULL, _IOFBF, BUFSIZE) != 0)    // 替代默认缓冲区
    {
        fputs("Can't create input buffer\n", stderr);
    }
    appen(fp, ft);
    if (ferror(fp) != 0) fprintf(stderr, "Error in read file %s \n", source);
    if (ferror(ft) != 0) fprintf(stderr, "Error in read file %s \n", 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);    // 从缓冲区写入文件
}

相关推荐