文件访问:C/C++/MFC

1. C语言

在C语言中,文件访问是通过一系列标准库函数来完成的,这些函数被定义在stdio.h(标准输入输出库)头文件中。
文件的访问主要通过以下几个函数实现:

函数说明
fopen()打开一个文件
fclose()关闭一个文件
fread()读取文件
fwrite()写入文件
fseek()移动文件指针到指定位置
ftell()获取文件指针当前位置
fgetc()从文件中读取一个字符
fputc()写入一个字符到文件中
  • Note:通过文件指针来实现文件的访问。
  1. 打开文件:
    FILE *fopen(const char *filename, const char *mode);
    此函数打开一个文件并返回一个文件指针,该文件指针可用于后续的文件操作。如果文件无法打开,则返回NULL。

    • filename 是文件名(可以包含路径)。
    • mode 是打开文件的模式,例如 “r”(只读)、“w”(只写,创建新文件或覆盖旧文件)、“a”(追加,写入数据到文件末尾)、“r+”(读写)等。
  2. 关闭文件:
    int fclose(FILE *stream);
    此函数关闭一个打开的文件。如果成功关闭文件,则返回0;否则返回EOF(一个定义在stdio.h中的特殊值,表示文件结束或发生错误)。

  3. 读取文件:
    size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
    此函数从文件中读取数据。函数返回实际读取的数据项的数量,如果发生错误或到达文件末尾,则可能小于count。

    • ptr 是一个指向内存块的指针,该内存块用于存储从文件中读取的数据。
    • size 是每个数据项的大小(以字节为单位)。
    • count 是要读取的数据项的数量。
    • stream 是文件指针。
  4. 写入文件:
    size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
    此函数将数据写入文件。函数返回实际写入的数据项的数量,如果发生错误,则可能小于count。

    • ptr 是一个指向要写入文件的数据的指针。
    • size、count 和 stream 的含义与fread相同。
  5. 文件定位:
    int fseek(FILE *stream, long offset, int whence);
    此函数设置文件位置指针。如果成功,则返回0;否则返回非零值。

    • offset 是相对于whence指定的位置的偏移量(以字节为单位)。
    • whence 可以是 SEEK_SET(文件开头)、SEEK_CUR(当前位置)或 SEEK_END(文件末尾)。
  6. 获取当前位置:
    long ftell(FILE *stream);
    此函数返回文件位置指针的当前位置(以字节为单位)。如果发生错误,则返回-1L。

  7. 检查文件结束:
    int feof(FILE *stream);
    此函数检查文件是否已到达末尾。如果到达末尾,则返回非零值;否则返回0。

  8. 清除文件结束和错误标志:
    void clearerr(FILE *stream);
    此函数清除与stream关联的文件结束和错误标志。

  9. 检查文件错误:
    int ferror(FILE *stream);
    此函数检查与stream关联的文件是否发生错误。如果发生错误,则返回非零值;否则返回0。

  10. 格式化输出或输入:
    int fscanf(FILE *fp, char *format, …);
    int fprintf(FILE *fp, char *format, …);

  11. 行输入和输出
    char *fgets(char *line, int maxline, FILE *fp);
    int fputs(char *line, FILE *fp);

1.1 打开并读取文件

#include <stdio.h>
#include <stdlib.h>
 
int main() {
    FILE *file = fopen("test.txt", "r");
    if (file == NULL) {
        printf("无法打开文件\n");
        return -1;
    }
 
    char ch;
    while ((ch = fgetc(file)) != EOF) {
        printf("%c", ch);
    }
 
    fclose(file);
    return 0;
}

1.2 写入文件

#include <stdio.h>
#include <stdlib.h>
 
int main() {
    FILE *file = fopen("test.txt", "w");
    if (file == NULL) {
        printf("无法打开文件\n");
        return -1;
    }
 
    fputc('A', file);
    fputc('B', file);
 
    fclose(file);
    return 0;
}

1.3 读取二进制文件

#include <stdio.h>
#include <stdlib.h>
 
typedef struct {
    int a;
    char b;
} Data;
 
int main() {
    FILE *file = fopen("test.bin", "rb");
    if (file == NULL) {
        printf("无法打开文件\n");
        return -1;
    }
 
    Data data;
    fread(&data, sizeof(Data), 1, file);
 
    printf("a: %d, b: %c\n", data.a, data.b);
 
    fclose(file);
    return 0;
}

1.4 写入二进制文件

#include <stdio.h>
#include <stdlib.h>
 
typedef struct {
    int a;
    char b;
} Data;
 
int main() {
    FILE *file = fopen("test.bin", "wb");
    if (file == NULL) {
        printf("无法打开文件\n");
        return -1;
    }
 
    Data data = {1, 'A'};
    fwrite(&data, sizeof(Data), 1, file);
 
    fclose(file);
    return 0;
}

1.5 文件指针的移动

#include <stdio.h>
#include <stdlib.h>
 
int main() {
    FILE *file = fopen("test.txt", "r");
    if (file == NULL) {
        printf("无法打开文件\n");
        return -1;
    }
 
    fseek(file, 2, SEEK_SET); // 将文件指针移动到第3个字符的位置
    printf("%c\n", fgetc(file));
 
    fclose(file);
    return 0;
}

2. C++

在C++中,文件访问与C语言非常相似,因为C++是在C语言的基础上构建的,并保留了C语言的大部分I/O功能。C++使用相同的文件操作函数,这些函数在(或<stdio.h>)头文件中定义。然而,C++还提供了自己的文件流类(如std::ifstream、std::ofstream和std::fstream),这些类位于头文件中,提供了更加面向对象的文件操作方式。

2.1 包含头文件

#include <fstream>

2.2 打开文件

使用 std::ifstream(输入文件流)或 std::ofstream(输出文件流)来打开文件。例如:

std::ifstream inputFile("input.txt"); // 打开文件以进行读取
std::ofstream outputFile("output.txt"); // 打开文件以进行写入

可以使用 std::fstream(文件流)来同时读取和写入文件。

2.3 检查文件是否成功打开

可以通过检查文件流对象是否有效来确认文件是否成功打开。

if (!inputFile) {
    std::cerr << "无法打开文件\n";
    return 1;
}

2.4 读取文件

使用 >> 运算符或 getline() 函数来从文件中读取数据。

int number;
inputFile >> number; // 读取一个整数

std::string line;
std::getline(inputFile, line); // 读取一行文本

2.5 写入文件

使用 << 运算符来将数据写入文件。

outputFile << "Hello, World!\n"; // 写入一行文本
outputFile << 42; // 写入一个整数

2.6 关闭文件

当文件流对象超出范围或被销毁时,文件会自动关闭。但是,你也可以显式地调用 close() 方法来关闭文件。

outputFile.close();

2.7 文件指针的移动和获取位置

使用 seekg()(对于输入流)和 seekp()(对于输出流)来移动文件指针。使用 tellg()(对于输入流)和 tellp()(对于输出流)来获取当前文件指针的位置。

inputFile.seekg(10, std::ios::beg); // 将输入文件的指针移动到第10个字节
std::streampos pos = inputFile.tellg(); // 获取当前输入文件的指针位置

2.8 实例

//读取文件
#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream file("test.txt"); // 打开文件以供读取

    if (!file) { // 检查文件是否成功打开
        std::cerr << "无法打开文件\n";
        return 1;
    }

    std::string line;
    // 逐行读取文件
    while (std::getline(file, line)) {
        std::cout << line << '\n';
    }

    file.close(); // 关闭文件
    return 0;
}
//写入文件
#include <fstream>
#include <iostream>

int main() {
    std::ofstream file("test.txt"); // 打开文件以供写入(如果文件不存在,则创建它)

    if (!file) { // 检查文件是否成功打开
        std::cerr << "无法打开文件\n";
        return 1;
    }

    file << "Hello, World!" << std::endl; // 写入数据到文件

    file.close(); // 关闭文件
    return 0;
}

C++的文件流类同样支持二进制文件的读写。你可以通过文件流的binary模式标志来指定文件应以二进制模式打开。但是,在大多数系统中,这并不是必须的,因为文件流默认就是二进制安全的。然而,在某些情况下(特别是跨平台操作时),明确指定二进制模式可能是有必要的。

std::ifstream file("test.bin", std::ios::binary); // 以二进制模式打开文件
// ... 读取操作 ...

std::ofstream file("test.bin", std::ios::binary); // 以二进制模式打开文件
// ... 写入操作 ...

note:使用文件流类进行文件操作通常比使用C风格的函数更加直观和易于管理,因为它们提供了更丰富的错误处理和更面向对象的接口。此外,文件流还支持更多的操作,如格式化输入/输出、操纵符重载等.

3. C语言和C++文件打开模式

C++和C语言在文件打开模式上有很多相似之处,但由于C++提供了更高级的封装,其使用方式略有不同。以下是一个简化的表格,列出了C++和C语言中常用的文件打开模式:

模式描述C++示例C示例
“r”以只读方式打开文件,文件必须存在std::ifstream file(“test.txt”, std::ios::in);FILE *file = fopen(“test.txt”, “r”);
“w”以写入方式打开文件,如果文件不存在则创建新文件,如果文件已存在则清空内容std::ofstream file(“test.txt”, std::ios::out);FILE *file = fopen(“test.txt”, “w”);
“a”以追加方式打开文件,如果文件不存在则创建新文件,如果文件已存在则在文件末尾追加内容std::ofstream file(“test.txt”, std::ios::out/std::ios::app);FILE *file = fopen(“test.txt”, “a”);
“r+”以读写方式打开文件,文件必须存在std::fstream file(“test.txt”, std::ios::in/std::ios::out);FILE *file = fopen(“test.txt”, “r+”);
“w+”以写读方式打开文件,如果文件不存在则创建新文件,如果文件已存在则清空内容std::fstream file(“test.txt”, std::ios::in/std::ios::out/std::ios::truncFILE *file = fopen(“test.txt”, “w+”);
“a+”以追加写读方式打开文件,如果文件不存在则创建新文件,如果文件已存在则在文件末尾追加内容std::fstream file(“test.txt”, std::ios::in /std::ios::out)
“b”以二进制模式打开文件(可以与上述模式组合使用)std::ifstream file(“test.bin”, std::ios::in/std::ios::binary);

4. MFC

在MFC(Microsoft Foundation Classes)中,CFile 类是一个用于文件操作的封装类,它提供了比标准C语言I/O函数更高级和面向对象的接口。使用 CFile 类,你可以更方便地打开、读取、写入和关闭文件。

4.1 头文件

#include <afxwin.h> // MFC 头文件
#include <afx.h>    // 包含CFile类的定义

4.2 打开文件

CFile file(_T("example.txt"), CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive);
if (!file.Open()) {
    AfxMessageBox(_T("无法打开文件"));
    return;
}

试图以创建(如果不存在)、写入和独占模式打开一个名为 example.txt 的文件。如果文件打开失败,显示一个消息框。

4.3 写入文件

CString str = _T("Hello, World!");
ULONGLONG pos = file.GetPosition(); // 获取当前文件指针位置
file.Write(str, (UINT)str.GetLength() * sizeof(TCHAR)); // 写入字符串到文件
file.Seek(pos, CFile::begin); // 如果需要,可以将文件指针移回原位

将一个字符串写入文件。Write 函数需要两个参数:要写入的数据的指针和要写入的数据的大小(以字节为单位)。

4.4 读取文件

ULONGLONG len = file.GetLength(); // 获取文件长度
if (len > 0) {
    CFileException e;
    char* buffer = new char[len];
    try {
        file.Read(buffer, len); // 读取整个文件
    }
    catch (CFileException* pEx) {
        e = *pEx;
        pEx->Delete();
        // 处理异常
    }
    // 使用 buffer 中的数据...
    delete[] buffer; // 释放内存
}

在这个例子中,我们首先获取文件的长度,然后分配足够的内存来存储整个文件的内容。我们使用 Read 函数来读取文件内容。注意,我们使用 CFileException 来处理可能发生的异常。

4.5 关闭文件

file.Close(); // 关闭文件

在完成文件操作后,使用 Close 函数关闭文件。虽然 CFile 的析构函数会自动关闭文件(如果尚未关闭),但显式关闭文件是一个好习惯。

MFC 主要用于Windows桌面应用程序的开发,并且依赖于Microsoft的Visual C++环境。如果你正在开发跨平台应用程序或不想依赖MFC,那么使用标准C++的 库可能是更好的选择。

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值