要想实现一个文件的基本写入需要用到下面三个函数(基本流程):
步骤 | 函数 | 说明 | 备注 |
---|---|---|---|
第一步 | fopen() | 打开文件 | fopen(“文件路径+文件名”, “模式(wb/ab/rb)”) 返回FILE* fp指针 |
第二步 | fwrite() | 写入文件 | fwrite(“写入的内容”, 1, “内容的大小(字节)”, “FILE* 指针对象”); |
第三步 | fclose() | 关闭文件 | fclose(“FILE* 指针对象”); 对文件进行写入/读取之后都需要关闭文件 |
#include
#include
// 文件写入:使用wb模式(清空内容之后再写入)
void file_fwrite_wb();
int main() {
file_fwrite_wb();
return 0;
}
// 文件写入:使用wb模式(清空内容之后再写入)
void file_fwrite_wb() {
// 文件路径
const char fileName[] = "F:/C++/file/a.txt";
// 打开文件
FILE* fp = fopen(fileName, "wb");
if (fp == NULL) {
printf("文件打开失败,文件路径不存在\n ");
return;
}
// 要写入的字符
char buf[] = "hello,world";
// 返回写入的字节数
int res = fwrite(buf, 1, 11, fp);
// 关闭文件
fclose(fp);
}
// 打开文件
FILE* fp = fopen(fileName, "ab");
#include
#include
// 以字符串的方式写入int类型数据
void file_fwrite_str();
int main() {
file_fwrite_str();
return 0;
}
// 以字符串的方式写入int类型数据
void file_fwrite_str() {
// 文件路径
const char fileName[] = "F:/C++/file/a.txt";
// 打开文件
FILE* fp = fopen(fileName, "wb");
if (fp == NULL) {
printf("文件打开失败,文件不存在\n ");
return;
}
// 要写入的字符
int buf[3] = {
0xA1, 0xB1, 0xC1 };
for (int i = 0; i < 3; i++)
{
char text[12];
// 加了一个,号分割数组的存储
sprintf(text, "%d,", buf[i]);
fwrite(text, 1, strlen(text), fp);
}
// 关闭文件
fclose(fp);
}
#include
#include
// 读取文件内容(读取全部内容)
void read_all_content();
int main() {
read_all_content();
return 0;
}
// 读取文件内容(读取全部内容)
void read_all_content() {
// 文件路径
const char fileName[] = "F:/C++/file/a.txt";
// 打开文件
FILE* fp = fopen(fileName, "rb");
if (fp == NULL) {
printf("文件打开失败,文件不存在\n ");
return;
}
// 第一种方式读取(直接读取):
char buf[12];
// 我的文件内容为: 161,177,193,
int n = fread(buf, 1, 12, fp);
// 可调试+断点,打开局部变量窗口查看buf的值
fclose(fp);
}
#include
#include
// 顺序读取
void read_buf_content();
int main() {
read_buf_content();
return 0;
}
// 顺序读取
void read_buf_content() {
// 文件路径
const char fileName[] = "F:/C++/file/a.txt";
// 打开文件
FILE* fp = fopen(fileName, "rb");
if (fp == NULL) {
printf("文件打开失败,文件路径不存在\n ");
return;
}
// 我的文件内容为: 161,177,193, 一共12个字节
// 所以我创建一个字节缓冲区(4个字节),下面分3次读取
char buf[4];
// 顺序读取(文件流):
// 如果文件很大,则无法一次性读完,可以采用顺序读取,每次读取一定长度,直到读取完
while (! feof (fp))
{
// 每次读取4个字节
int n = fread(buf, 1, 4, fp);
if (n > 0) {
// n 读取到字节数
printf("read %d bytes \n", n);
// 下一次读取会覆盖上次读取(buf缓冲区)的内容,断点+调试
}
}
// 注意: feof()函数是检测文件是否已经读取到末尾
fclose(fp);
}
随机访问:比如MP3、MP4等文件拖动快进时就是随机读取( fseek()函数)) | |
功能 | 示列 |
调到第100个字节位置 | fseek(fp, 100, SEEK_SET); |
调到倒数100个字节的位置 | fseek(fp, 100, SEEK_END); |
调到当前位置往前100个字节 | fseek(fp, -100, SEEK_CUR); |
调到当前位置的往后100个字节 | fseek(fp, 100, SEEK_CUR); |
#include
#include
// 随机访问读取
void random_read_content();
int main() {
random_read_content();
return 0;
}
// 随机访问读取
void random_read_content() {
// 文件路径+文件名
const char fileName[] = "F:/C++/file/a.txt";
FILE* fp = fopen(fileName, "rb");
if (fp == NULL) {
printf("文件打开失败,文件路径不存在\n ");
return;
}
// 我的文件内容为: 161,177,193, 一共12个字节
// 读取文件内容的buf缓冲区
unsigned char buf[4];
// 从第8个字节开始读取,读取四个
fseek(fp, 8, SEEK_SET);
// n 返回的字节数
int n = fread(buf, 1, 4, fp);
fclose(fp);
}
#include
#include
// 以文本形式存储(按行存储,就是在结尾加一个\n)
void file_fwrite_text();
int main() {
file_fwrite_text();
return 0;
}
// 以文本形式存储(按行存储,就是在结尾加一个\n)
void file_fwrite_text() {
// 文件路径+文件名
const char fileName[] = "F:/C++/file/text.txt";
FILE* fp = fopen(fileName, "wb");
if (fp == NULL) {
printf("文件打开失败,文件路径不存在\n ");
return;
}
// 比如我需要保存服务器的IP和端口号到配置文件(按行存储)
char ip[] = "192.169.0.1";
int port = 8080;
// 定义一行的缓冲区
char line[256];
// 保存ip
sprintf(line, "ip=%s\n", ip);
fwrite(line, 1, strlen(line), fp);
// 保存端口号
sprintf(line, "port=%d\n", port);
fwrite(line, 1, strlen(line), fp);
fclose(fp);
}
使用fgets()函数,内部会检查,如果都到\n时,停止读取。返回实际读取的字节
#include
#include
#include
// 按行读取、解析数据(fgets()函数,内部会检查,如果都到\n时,停止读取。返回实际读取的字节)
void read_line_content();
int main() {
read_line_content();
return 0;
}
// 按行读取、解析数据
void read_line_content() {
// 文件路径+文件名
const char fileName[] = "F:/C++/file/text.txt";
FILE* fp = fopen(fileName, "rb");
if (fp == NULL) {
printf("文件打开失败,文件不存在\n ");
return;
}
// 我的文本数据
//ip=192.169.0.1
//port=8080
// 按行读取数据的缓冲区(一行最多512个字节)
char buf[512];
// feof()函数是检测文件是否已经读取到末尾
while (! feof(fp))
{
char* line = fgets(buf, 512, fp);
if (line) {
//printf("got: %s \n", line);
// 解析字符串 (sscanf()只适提取数字,不适合字符串), 需要自己解析(比较麻烦)
// 字符串为指定char的下标
int eq = 0;
// 获取字符串长度
int len = strlen(line);
// 动态创建新的字符串对象
char* copy = (char*)malloc(len + 1);
// copy字符创的下标
int count = 0;
for (int i = 0; i < len; i++)
{
char ch = line[i];
// 等于换行符的时候跳过
if (ch == '\n') continue;
// 如果当下边的char等于'='是。获取'='的下标,赋值给eq
if (ch == '=')
eq = i;
if (eq && i > eq) {
copy[count] = line[i];
count++;
}
}
// 字符串结束(为什么len - (eq + 1) -1)
// 因为len是原本字符串的长度,我们截取之后长度不够;
// eq + 1 = 下标是从0开始的; 为什么还要 -1呢, '\n'也算一个字节;
copy[len - (eq + 1) - 1] = 0;
// 解析之后赋值给当前的line
strcpy(line, copy);
// 释放
free(copy);
printf("read: %s \n", line);
}
}
fclose(fp);
}