栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C primer plus学习笔记 —— 4、文件IO(输入/输出)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C primer plus学习笔记 —— 4、文件IO(输入/输出)

文章目录
    • 与文件通信
      • 文本文件和二进制文件
        • 区别
    • main函数传参与exit函数
      • main参数
      • exit()函数
    • 文件操作函数
      • fopen()函数
      • fclose()函数
      • getc()和putc()函数(文件字符IO)
      • fgets(), fputs() (文件字符串IO)
      • fprintf(), fscanf()(文件IO)
      • fseek()和ftell()函数
      • fwrite()和fread()函数
        • fwrite
        • fread函数
    • 综合示例

文件作为用于存储程序文档图片,等很多其他种类的信息。作为程序员必须学会创建文件及读取文件信息。

与文件通信 文本文件和二进制文件

https://blog.csdn.net/colourful_sky/article/details/80334250
所有文件内容都以二进制(0/1)存储。
C语言把文件看作一系列连续字节,每个字节都能被单独读取。与Unix的文件结构对应。
有两种文件形式,文本文件和二进制文件。

计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。二进制或者文本与文件的格式并没有任何关系,而是文件流操作时对数据的表达方式不同。

区别
  1. 读取单位:如果文件最初使用字符存储,比如C字符串,该文件就是文本文件,文本文件读取都是以字符为单位。也就是byte为单位。如果文件二进制值代表机器语言,则该文件就是二进制文件,包含二进制内容。二进制文件是以bit为单位。

  2. 可读性:这里的可读性是从软件使用者角度来说的,因为我们用通用的记事本工具就几乎可以浏览所有文本文件,所以说文本文件可读性好;而读写一个具体的二进制文件需要一个具体的文件解码器,所以说二进制文件可读性差,比如读BMP文件,必须用读图软件.

  3. 举例:文本文件中的一个数字65536,需要用5个字节来存储;但是用二进制格式,采用int存储,仅仅需要2个字节。而二进制文件elf和bmp等,都往往有一个head,告诉你文件信息和解释方式。

  4. 操作系统对换行符(‘n’)的处理不同: 文本文件,操作系统会对’n’进行一些隐式变换,因此文本文件直接跨平台使用会出问题。在Windows下,写入’n’时,操作系统会隐式的将’n’转换为”rn”,再写入到文件中;读的时候,会把“rn”隐式转化为’n’,再读到变量中。在Linux下,写入’n’时,操作系统不做隐式变换。二进制文件,操作系统不会对’n’进行隐式变换,很多二进制文件(如电影、图片等)可以跨平台使用。

  5. 优缺点:因为文本文件与二进制文件的区别仅仅是编码上不同,所以他们的优缺点就是编码的优缺点,。一般认为,文本文件编码基于字符定长,译码容易些;二进制文件编码是变长的,所以它灵活,存储利用率要高些,译码难一些(不同的二进制文件格式,有不同的译码方式)。关于空间利用率,想想看,二进制文件甚至可以用一个比特来代表一个意思(位操作)所以更高,而文本文件任何一个意思至少是一个字符。

main函数传参与exit函数 main参数
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: %s filenamen", argv[0]);
        exit(EXIT_FAILURE);
    }
    return 0;
}

argc 表示传入的参数数量
argv字符串的参数,不管是书写的整数还是浮点数,全部被认为是字符串。
argv[0] = 运行的可执行程序的名称
argv[1] 可执行程序后面的第一个,后面以此类推。

exit()函数

exit函数关闭所有打开的文件并结束程序。
他会返回一个值给操作系统。一般正常结束传0。异常结束非0值。
exit和return函数的区别:
return在其他函数中会退出该函数。而exit是直接结束整个程序。

文件操作函数 fopen()函数

该函数作用:打开一个文件,并返回文件指针(其他函数使用该文件指针操作文件)。
fopen("1.txt","r");
第一个参数是打开的文件名。
第二个参数是打开方式。

用r的时候后续不能用写操作,只能够read。
用r+的时候,可以写入。
用w的时候不能读操作,只能写入。
用w+的时候可以读写。
r+和w+区别在于:r+如果文件不存在则失败,w+如果文件不存在则创建新文件。
a+和w+区别:a+会在原内容上追加,而w+会清除原内容。

新标准wx,表示必须创建新文件然后打开。如果是已有文件则直接失败报错。

程序打开文件后,会返回一个文件指针,文件指针类型为FILE。他不知想实际文件而是指向一个包含文件信息的数据对象。这个对象包含了要操作的哪个文件以及一些缓冲区信息。
FILE *f = fopen("1.txt","r");

fclose()函数

fclose()关闭函数如果关闭成功,返回0,否则返回EOF。

if (fclose(fp) != 0) 
	printf("error");
getc()和putc()函数(文件字符IO)

他们getchar()函数还有putchar()函数很类似,区别在于:
getchar()是从标准输入中获取一个字符
getc(fp) 是从FILE指针fp中获取一个字符

putchar(ch)将字符输出到标准输出
putc(ch, fp) 将字符输出到文件FILE指针fp

所以他们的使用代码如下

fgets(), fputs() (文件字符串IO)

他们和字符串IO函数gets()和puts()类似,但他们是从文件中输入输出字符串。
从文件读取字符串
fgets(buf, STLEN, fp);
第一个参数char类型数组名称,第二个参数表示字符串长度,第三个参数是待读取的文件指针。
fgets()从文件读取字符串会在三种情况下读取完成:

  1. 读取输入遇到换行符
  2. 读取到文件结尾遇到EOF
  3. 读取STLEN-1个字符

fgets 会在遇到EOF的时候返回NULL值,可以用它来检查是否读到文件末尾。如果没遇到EOF则返回第一个参数buf地址。
并且fgets会在读取到的字符串后面加入一个空字符使之成为一个字符串并赋值给char数组buf。

字符串输出到文件
fputs(buf, fp);
第一个参数是字符串地址,第二个参数是文件FILE指针。
fputs不会在输出到文件中加入换行符。

fprintf(), fscanf()(文件IO)

与printf和scanf基本相同。
他们是文件的输入和输出函数,
而且fprint和fscanf要在第一个参数指定FILE指针。
如果使用标准输入和输出,则他们的功能就和printf和scanf相同了。标准输入输出FILE指针是stdin和stdout。

fseek()和ftell()函数

fseek(fp, 10L, SEEK_CUR);该函数作用是移动文件指针到特定位置。
参数1:文件指针
参数2:偏移量,从起始点的偏移,需要long类型,可正可负
参数3:起始点。
返回值:0为正常,-1为报错

ftell(fp);该函数是返回从当前文件指针位置距文件开始处的字节数,一般和fseek联合使用。
举例:
fseek(fp,0L, SEEK_END); //将文件指针移动到文件末尾
ftell(fp); //计算该文件指针到文件起始位置的总字节数,返回long类型

fwrite()和fread()函数

他们是以二进制形式向文件中读写数据的函数。
注意区别,fgets(), fputs() 是以字符存储
举个例子:
比如我要存储这个数num

如果我存储4位则存储的0.333则每个字符占用一个存储空间。
如果我存储8位则存储空间就变大了。

为了保证存储一致。我们向存储double类型的数据大小就占用固定字节。
如果程序用所用的表示法把数据存储到文件中,我们就称他为以二进制形式存储数据。

下图展示文本形式和二进制形式存储的不同点。

二进制形式读写

fwrite

该函数把二进制数据写入文件

第一个参数是待写入数据块的地址
第二个参数是数据块大小,单位是byte
第三个参数是写几块。
第四个参数是写入文件。

fread函数

二进制形式读取文件

  1. 读取文件数据拷贝到的内存中的地址
  2. 数据块大小
  3. 几个数据块
  4. 文件指针
综合示例
#include 
#include 
#include 
#define BUFSIZE 4096
#define SLEN 81
void append(FILE *source, FILE *dest);
char * s_gets(char * st, int n);

int main(void)
{
    FILE *fa, *fs;	// fa for append file, fs for source file
    int files = 0;  // number of files appended
    char file_app[SLEN];  // name of append file
    char file_src[SLEN];  // name of source file
    int ch;
    
    puts("Enter name of destination file:");
    s_gets(file_app, SLEN);
    if ((fa = fopen(file_app, "a+")) == NULL)
    {
        fprintf(stderr, "Can't open %sn", file_app);
        exit(EXIT_FAILURE);
    }
    if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0)
    {
        fputs("Can't create output buffern", stderr);
        exit(EXIT_FAILURE);
    }
    puts("Enter name of first source file (empty line to quit):");
    while (s_gets(file_src, SLEN) && file_src[0] != '')
    {
        if (strcmp(file_src, file_app) == 0)
            fputs("Can't append file to itselfn",stderr);
        else if ((fs = fopen(file_src, "r")) == NULL)
            fprintf(stderr, "Can't open %sn", file_src);
        else
        {
            if (setvbuf(fs, NULL, _IOFBF, BUFSIZE) != 0)
            {
                fputs("Can't create input buffern",stderr);
                continue;
            }
            append(fs, fa);
            if (ferror(fs) != 0)
                fprintf(stderr,"Error in reading file %s.n",
                        file_src);
            if (ferror(fa) != 0)
                fprintf(stderr,"Error in writing file %s.n",
                        file_app);
            fclose(fs);
            files++;
            printf("File %s appended.n", file_src);
            puts("Next file (empty line to quit):");
        }
    }
    printf("Done appending. %d files appended.n", files);
    rewind(fa);
    printf("%s contents:n", file_app);
    while ((ch = getc(fa)) != EOF)
        putchar(ch);
    puts("Done displaying.");
    fclose(fa);
    
    return 0;
}

void append(FILE *source, FILE *dest)
{
    size_t bytes;
    static char temp[BUFSIZE]; // allocate once
    
    while ((bytes = fread(temp,sizeof(char),BUFSIZE,source)) > 0)
        fwrite(temp, sizeof (char), bytes, dest);
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;
    
    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, 'n');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '';          // place a null character there
        else
            while (getchar() != 'n')
                continue;
    }
    return ret_val;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1012365.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号