不可或缺 Windows Native (10) - C 语言: 文件

[源码下载]

作者:webabcd

介绍
不可或缺 Windows Native 之 C 语言

  • 文件

示例
cFile.h

#ifndef _MYHEAD_FILE_
#define _MYHEAD_FILE_ 

#ifdef __cplusplus
extern "C"
#endif  

char *demo_cFile(char *rootPath);

#endif  

cFile.c

/*
 * 文件
 *
 * 从用户角度讲,文件可分为普通文件和设备文件两种
 * 1、普通文件是指保存在磁盘或其它外部介质上的一段数据
 * 2、设备文件是指与主机相联的各种外部设备,操作系统会把各种外部设备也看作是一个文件来进行管理。比如:通常把显示器定义为标准输出文件,键盘定义为标准输入文件
 *
 * 从文件编码的方式来看,文件可分为 ASCII 码文件(文本文件)和二进制文件
 * 1、ASCII 文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的 ASCII 码。比如:字符串 1234567 按字符存放成文本文件,占用 7 个字节
 * 2、二进制文件是按二进制的编码方式来存放文件的。比如:数字 1234567 按整型存放成二进制文件,占用 4 个字节
 *
 * 关于 mkdir(make directory) - 创建目录,rmdir(remove directory) - 删除目录 之类的函数,以后再写
 *
 *
 * 注:EOF(end of file) - 文件的结束标志
 */

#include "pch.h"
#include "cFile.h"
#include "cHelper.h"

void file_demo1();
void file_demo2();
void file_demo3();
void file_demo4();
void file_demo5();

char *_rootPath;

char *demo_cFile(char *rootPath)
{
    _rootPath = rootPath;

    // 写入文本文件
    file_demo1();

    // 读取文本文件
    file_demo2();

    // 以格式化的方式读写文本文件
    file_demo3();

    // 读写二进制文件
    file_demo4();

    // 文件的内部定位(随机读写,即任意位置读写)
    file_demo5();

    return str_concat2("演示文件的保存路径:", rootPath);
}

// 写入文本文件
void file_demo1()
{
    // 文件指针 - 指向文件的指针(FILE *指针变量标识符)

    // 需要访问的文件路径
    char *fileName = str_concat2(_rootPath, "\\c_file_demo1.txt");

    // fopen - 用指定的方式打开指定路径的文件,并返回文件指针(FILE 是由系统定义的结构体,fp 是指向 FILE 的文件指针)
    FILE *fp = fopen(fileName, "wt+"); // 第 2 个参数是文件打开方式,其说明参见后面的注释
    if (fp == NULL)
    {
        // 如果 fopen 返回空指针,则说明文件打开失败(errno 中保存着最近一次的错误)
        int errNum = errno; // 关于 errno 的预定义参见 errno.h
    }
    else
    {
        // rewind - 让指定的文件指针所指文件的内部位置指针移到文件头
        rewind(fp);

        // fputc - 向指定的文件写入字符(这里的 EOF 代表写入失败)
        if (fputc(‘w‘, fp) == EOF)
        {
            // ferror - 检查文件在读写时是否出错,返回值为 0 表示正常,否则表示有错
            int errNum = ferror(fp); // 关于 errno 的预定义参见 errno.h

            // clearerr - 清除出错标志,使它为 0 值。
            clearerr(fp);
        }

        // fputs - 向指定的文件写入字符串(这里的 EOF 代表写入失败)
        if (fputs("ebabcd\nwanglei", fp) == EOF)
        {
            // ferror - 检查文件在读写时是否出错,返回值为 0 表示正常,否则表示有错
            int errNum = ferror(fp); // 关于 errno 的预定义参见 errno.h

            // clearerr - 清除出错标志,使它为 0 值。
            clearerr(fp);
        }

        // fclose - 打开文件后,必须要用 fclose 关闭文件,返回 0 则说明文件正常关闭了
        int fcloseResult = fclose(fp);
    }

    free(fileName);
}

// 读取文本文件
void file_demo2()
{
    char *fileName = str_concat2(_rootPath, "\\c_file_demo1.txt");

    FILE *fp = fopen(fileName, "rt");
    if (fp == NULL)
    {
        int errNum = errno;
    }
    else
    {
        rewind(fp);

        // fgetc - 一个字符一个字符地读,如遇到 EOF 则文件读完或出错(每个文件末尾都有结束标志 - EOF)
        char ch = fgetc(fp);
        while (ch != EOF)
        {
            // 每读一个字符,则内部位置指针会向后移动一个字节
            ch = fgetc(fp);
        }

        // feof - 检查文件是否结束(即内部位置指针是否指向 EOF),如结束,则返回非零值,否则返回 0
        int isEnd = feof(fp); // 非零值

        rewind(fp);

        // feof - 检查文件是否结束(即内部位置指针是否指向 EOF),如结束,则返回非零值,否则返回 0
        isEnd = feof(fp); // 0

        /*
         * fgets(str, n, fp) - 读取字符串函数
         *     str - 字符数组名,由于保存读取到的字符串
         *     n - 读出 n-1 个字符并送入字符数组 str 中,然后在结尾加‘\0‘(在读出 n-1 个字符之前,如遇到了换行符或 EOF,则读取结束)
         *     fp - 文件指针
         */
        char str[32];
        while (fgets(str, 32, fp) != NULL)
        {
            // 本例会循环 2 次
            // 第 1 次 str 的结果为:webabcd\n
            // 第 2 次 str 的结果为:wanglei
        }

        fclose(fp);
    }

    free(fileName);
}

// 以格式化的方式读写文本文件
void file_demo3()
{
    char *fileName = str_concat2(_rootPath, "\\c_file_demo2.txt");

    FILE *fp = fopen(fileName, "wt+");
    if (fp == NULL)
    {
        int errNum = errno;
    }
    else
    {
        // fprintf(file print formatted) - 以格式化的方式写入字符串(返回值为写入的字节数)
        int fprintfResult = fprintf(fp, "%s %d %d\n", "webabcd", 100, 20); // 15

        rewind(fp);

        int num;
        int age;
        char name[32];

        // fscanf(file scan formatted) - 以格式化的方式读取字符串(返回值为读取的成员数)
        int fscanfResult = fscanf(fp, "%s %d %d\n", name, &num, &age); // 3

        fclose(fp);
    }

    free(fileName);
}

// 读写二进制文件
void file_demo4()
{
    struct employee
    {
        int num;
        char name[32];
    } w[2] = { { 100, "wanglei" }, { 200, "webabcd" } }, r[2], *ww, *rr;

    ww = w;
    rr = r;

    char *fileName = str_concat2(_rootPath, "\\c_file_demo3.b");

    FILE *fp = fopen(fileName, "wt+");
    if (fp == NULL)
    {
        int errNum = errno;
    }
    else
    {
        /*
         * fwrite(buffer, size, count, fp) - 写入二进制数据(返回值为成功写入的数据块数)
         *     buffer - 需要写入的数据的指针
         *     size - 每一个数据块的字节数
         *     count - 需要写入的数据块数
         *     fp - 文件指针
         */
        int fwriteResult = fwrite(ww, sizeof(struct employee), 2, fp); // 2

        rewind(fp);

        /*
         * fread(buffer, size, count, fp) - 读取二进制数据(返回值为成功读取的数据块数)
         *     buffer - 需要保存读取数据的指针
         *     size - 每一个数据块的字节数
         *     count - 需要读取的数据块数
         *     fp - 文件指针
         */
        int freadResult = fread(rr, sizeof(struct employee), 2, fp);

        fclose(fp);
    }

    free(fileName);
}

// 文件的内部定位(随机读写,即任意位置读写)
void file_demo5()
{
    struct employee
    {
        int num;
        char name[32];
    } w[2] = { { 100, "wanglei" }, { 200, "webabcd" } }, r[1], *ww, *rr;

    ww = w;
    rr = r;

    char *fileName = str_concat2(_rootPath, "\\c_file_demo4.b");

    FILE *fp = fopen(fileName, "wt+");
    if (fp == NULL)
    {
        int errNum = errno;
    }
    else
    {
        int fwriteResult = fwrite(ww, sizeof(struct employee), 2, fp);

        /*
         * rewind(fp) - 把文件内部位置指针移到文件头
         *     fp - 文件指针
         */
        rewind(fp);

        /*
         * fseek(fp, offset, origin) - 移动文件内部位置指针
         *     fp - 文件指针
         *     offset - 相对于 origin 的位移字节数(长整形,如果用常量的话记得加“L”)
         *     origin - 位移起始点
         *         SEEK_SET(0) - 文件头
         *         SEEK_CUR(1) - 当前位置
         *         SEEK_END(2) - 文件尾
         */
        fseek(fp, sizeof(struct employee), SEEK_SET);

        int freadResult = fread(rr, sizeof(struct employee), 1, fp); // 200, "webabcd"

        fclose(fp);
    }

    free(fileName);
}

/*
 * 关于文件打开方式的说明,即 fopen 的第 2 个参数
 * rt     只读打开一个文本文件,只允许读数据
 * wt     只写打开或建立一个文本文件,只允许写数据
 * at     追加打开一个文本文件,并在文件末尾写数据
 * rb     只读打开一个二进制文件,只允许读数据
 * wb     只写打开或建立一个二进制文件,只允许写数据
 * ab     追加打开一个二进制文件,并在文件末尾写数据
 * rt+     读写打开一个文本文件,允许读和写
 * wt+     读写打开或建立一个文本文件,允许读写
 * at+     读写打开一个文本文件,允许读,或在文件末追加数据
 * rb+     读写打开一个二进制文件,允许读和写
 * wb+     读写打开或建立一个二进制文件,允许读和写
 * ab+     读写打开一个二进制文件,允许读,或在文件末追加数据
 *
 * 关于上面字符的说明
 * r(read)        读
 * w(write)        写
 * a(append)    追加
 * t(text)        文本文件,可省略不写
 * b(banary)    二进制文件
 * +            读和写
 */

OK
[源码下载]

时间: 2024-10-05 03:54:01

不可或缺 Windows Native (10) - C 语言: 文件的相关文章

不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 结构体 共用体 枚举 类型定义符 示例cStruct.h #ifndef _MYHEAD_STRUCT_ #define _MYHEAD_STRUCT_ #ifdef __cplusplus extern "C" #endif char *demo_cStruct(); #endif cStruct.c /* * 结构体,共用体,枚举,类型定义符 * * 注:结构体变量在做参数传递时,其内每个

不可或缺 Windows Native (7) - C 语言: 指针

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 指针 示例cPointer.h #ifndef _MYHEAD_POINTER_ #define _MYHEAD_POINTER_ #ifdef __cplusplus extern "C" #endif char *demo_cPointer(); #endif cPointer.c /* * 指针 */ #include "pch.h" #include "c

不可或缺 Windows Native (6) - C 语言: 函数

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 函数 示例cFunction.h #ifndef _MYHEAD_FUNCTION_ #define _MYHEAD_FUNCTION_ #ifdef __cplusplus extern "C" #endif // 函数声明 // 像这种在 .h 中声明的函数,如果想被外部文件调用的话,则外部文件不用再声明即可调用 char *demo_cFunction(); long recursion

不可或缺 Windows Native 系列文章索引

[源码下载] 作者:webabcd 1.不可或缺 Windows Native (1) - C 语言: hello c 介绍不可或缺 Windows Native 之 C 语言 在 Windows Store Apps 中调用 C/C++ hello c 2.不可或缺 Windows Native (2) - C 语言: 常量,变量,基本数据类型 介绍不可或缺 Windows Native 之 C 语言 常量 变量 基本数据类型 3.不可或缺 Windows Native (3) - C 语言:

不可或缺 Windows Native (14) - C++: 文件

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 文件 示例CppIO2.h #pragma once #include <string> using namespace std; namespace NativeDll { class CppIO2 { public: string Demo(string rootPath); }; } CppIO2.cpp /* * 文件 */ #include "pch.h" #include

不可或缺 Windows Native (24) - C++: 运算符重载, 自定义类型转换

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 运算符重载 自定义类型转换 示例CppOperator.h #pragma once #include <string> using namespace std; namespace NativeDll { class CppOperator { public: string Demo(); }; } CppOperator.cpp /* * 运算符重载, 自定义类型转换 */ #include &qu

不可或缺 Windows Native (12) - C++: 引用类型

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 引用类型 示例CppReference.h #pragma once #include <string> using namespace std; namespace NativeDll { class CppReference { public: string Demo(); }; } CppReference.cpp /* * 引用类型 * * 引用也可以称之为“别名” * * 注: * 1.声明引

不可或缺 Windows Native (19) - C++: 对象的动态创建和释放, 对象的赋值和复制, 静态属性和静态函数, 类模板

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 对象的动态创建和释放 对象的赋值和复制 静态属性和静态函数 类模板 示例1.CppEmployee 类CppEmployee.h #pragma once #include <string> using namespace std; namespace NativeDll { class CppEmployee { int Number; // 默认为 private private: // 以下都是

不可或缺 Windows Native (20) - C++: 友元函数, 友元类

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 友元函数 友元类 示例演示友元函数, 友元类CppClass4.h #pragma once #include <string> using namespace std; namespace NativeDll { class CppClass4 { public: string Demo(); }; } CppClass4.cpp /* * 友元(friend)函数, 友元类 * * 友元函数: C+