<19> 文件

文件(资源)
操作系统把硬件抽象为文件,统一打开、关闭、读和写来对待。
在系统里泛指所有的设备,也可以叫资源。
一个文件只能被一个程序打开(共享文件除外)
安全检查:
数据设计到引用操作资源问题,包括堆、文件和句柄等,每调用一个函数都需要假设返回错误值。如果操作失败应该做错误处理。(自动区除外【堆、全局变量】)。其他任何函数都要检查返回值。

打开
文件的默认打开方式为 t (文本),二进制打开才支持以下操作:① 二进制的读写 。 ② 文件指针的自由访问。(文本方式不支持,时灵时不灵的)
注意:二进制方式不要用文本的函数,否则不能保证其安全性以及正确性。(看库的实行者)

fopen

include <stdio.h>

FILE *fopen(const char *filename, const char *mode);

include <stdio.h> | #include <wchar.h>

FILE *_wfopen(const wchar_t *filename, const wchar_t *mode);

//e.g.
FILE *fp = NULL;
fp = open("Test.bin", "r");

//正常文件路径 "c:\User\Test.bin"
//函数中应写为 "c:\User\Test.bin"

作用:打开文件。
参数:filename文件名,mode启用的访问类型。
返回值:返回指向打开文件的指针。错误返回NULL。
注意:fopen支持Unicode文件流,支持的编码值为UNICODE、utf-8和utf-16le。打开Unicode文件需要将指定所需编码的ccs标志传递给fopen。
文件名是要打开文件的文件名字,可以是包含盘符、路径文件名、扩展名的文件标识符。但在书写时要符合C语言的规定。
FILE *fp = fopen("Test.bin"、"rt+,ccs = encoding"); //打开Unicode文件流

文件打开方式 mode
打开文件时的处理文件方式决定了系统可以对文件进行的操作。
用“w”或者“w+”方式打开一个有数据的文件,将删除所有文件已有内容。如果打开一个不存在的文件,则会创建该文件。
文件操作主要以二进制文件为主,使用时在mode后面加上b。
mode 处理方式 文件不存在时 文件存在时 向文件输入 从文件输出
r 读取 出错 打开文件 × √
w 写入 建立新文件 覆盖原有文件 √ ×
a 追加 建立新文件 在原有文件后追加 √ ×
r+ 读取/写入 出错 打开文件 √ √
w+ 写入/读取 建立新文件 覆盖原有文件 √ √
a+ 读取/追加 建立新文件 在原有文件后追加 √ √

eg:
FILE* fp = NULL;
fp = fopen("1.bin","rb+");
if (fp == NULL)
{
fp = fopen("1.bin", "wb+");
if (fp == NULL)
{
Error
//goto EXIT_PROC;
}
}

关闭
fclose

include <stdio.h>

int fclose(FILE *stream);
//e.g.
if (fp != NULL)
{
fclose(fp); //将文件类型指针fp所指向的文件关闭,fp不再指向该文件
fp = NULL;
}

作用:关闭流。
参数:stream指向文件结构的指针。
返回值:成功关闭返回0。错误返回EOF。
注意:C语言文件使用完后,应该立即关闭文件,防止由于误操作等原因破坏已经打开的文件。

按数据块读写
fwrite

include <stdio.h>

//fwrite(写入文件数据块的存放地址,一个数据块的字节数,数据块的个数,文件型指针变量)
size_t fwrite(const void *buffer, size_t size, size_t count, FILE *stream);
//e.g.
fwrite(szHello, sizeof(szHello), 1, fp);

作用:将数据写入流(不是文件)。
参数:buffer指向要写入的数据的指针,size项大小(以字节为单位),count要写入的项的最大数量,stream指向文件结构体的指针。
返回值:返回实际写入的完整项的数量(count),错误则返回小于count的值。
需要注意的地方:字符串最好整体写入,单个字符写入如果失败异常处理比较复杂。

fread

include <stdio.h>

//fread (从文件读取数据块的存放地址,一个数据块的字节数,数据块的个数,文件指针变量)
size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
//e.g.
fread(szHello, sizeof(szHello), 1, fp);

作用:从流读取数据(不是文件)。
参数:buffer数据的存储位置,size项大小(以字节为单位),count要读取的项的最大数量,stream指向文件结构体的指针。
返回值:返回实际读取的完整项的数量count,错误则返回小于count的值。

提交缓存:fflush

include <stdio.h>

intfflush(FILE *stream);
//e.g.
fflush(fp);

作用:刷新流(设备)。提交数据写入到文件。
参数:stream指向文件结构的指针。
返回值:缓冲区成功刷新返回0。 在指定流无缓冲区或处于打开状态以仅供读取的情况下,也会返回0。 错误异常返回EOF。
需要注意的地方:fflush提交和fclose关闭不一样,提交不关文件,不释放缓存,只是把缓存中的内容强制写文件。

提交文件的两种方式:

  1. fflush(函数指针)
  2. fclose(函数指针)

缓存结构

include "stdafx.h" // 预编译头文件,通常用于Visual Studio项目,包含常用的标准库和系统库头文件

include <stdio.h> // 标准输入输出库,用于文件操作等

include <windows.h> // Windows API头文件,虽然在这个例子中未直接使用Windows API

include <crtdbg.h> // 用于调试的库,如内存泄漏检测等(此例中未直接使用)

// 主函数,_tmain是main的Windows特定版本,支持Unicode
int _tmain(int argc, _TCHAR* argv[])
{
FILE* fp = NULL; // 声明文件指针fp,初始化为NULL

// 尝试以读写二进制模式("rb+")打开文件"Test.bin"
fp = fopen("Test.bin", "rb+");
if (fp == NULL)
{
    // 如果文件不存在或无法以读写模式打开,则尝试以写读二进制模式("wb+")创建文件
    fp = fopen("Test.bin", "wb+");
    if (fp == NULL)
    {
        // 如果仍然无法打开或创建文件,则退出程序
        exit(-1);
    }
}

// 定义一个结构体tagTest,用于存储不同类型的数据
struct tagTest
{
    int n;        // 整数
    float f;      // 浮点数
    double d;     // 双精度浮点数
    char szBuf[20]; // 字符数组,用于存储字符串
};

// 初始化结构体数组test,包含三个元素
struct tagTest test[] = {
    { 1, 3.14f, 0.618, "Hello" },
    { 2, 4.14f, 1.618, "Jack" },
    { 3, 5.14f, 2.618, "jjyy" },
};

// 将结构体数组test写入到文件中
// 注意:这里应该使用sizeof(struct tagTest) * 数组元素个数作为fwrite的第二个参数
// 但由于只写入一个数组(即整个数组作为一个整体写入),所以数组元素个数为1
if (fwrite(test, sizeof(struct tagTest) * sizeof(test) / sizeof(test[0]), 1, fp) != 1)
{
    // 如果写入失败,则获取错误码并退出程序
    int nError = ferror(fp);
    exit(nError);
}

// 刷新文件流,确保所有数据都被写入到文件中
if (EOF == fflush(fp))
{
    // 如果刷新失败,则获取错误码并退出程序
    int nError = ferror(fp);
    exit(nError);
}

// 移动文件指针到倒数第二个结构体元素之后(准备修改最后一个元素)
int nSize = sizeof(struct tagTest);
fseek(fp, -nSize, SEEK_CUR);

// 修改test数组的最后一个元素的浮点数成员f
test[2].f = 66.66f;

// 将修改后的最后一个结构体元素写回到文件中
if (fwrite(&test[2], sizeof(test[2]), 1, fp) != 1)
{
    // 如果写入失败,则获取错误码并退出程序
    int nError = ferror(fp);
    exit(nError);
}

// 再次刷新文件流
if (EOF == fflush(fp))
{
    // 如果刷新失败,则获取错误码并退出程序
    int nError = ferror(fp);
    exit(nError);
}

// 关闭文件,并将文件指针置为NULL
if (fp)
{
    fclose(fp);
    fp = NULL;
}

// 程序正常结束
return 0;

}

posted @   kksllss  阅读(0)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示