C++文件操作(1)

news2024/11/15 12:31:29

C++文件操作

  • 1.文本的写入及读取
    • 文本文件写入
    • 文本文件读取
  • 2.二进制文件的写入及读取
    • 二进制文件写入
    • 二进制文件读取
  • 3.小结

C++也有处理文件的能力,其功能实现依赖文件流。文件流是C++中用来处理文件输入输出的一种流类。文件流可以用于从文件中读取数据或将数据写入到文件中。C++中的文件流类包括ifstream(用于从文件中读取数据)、ofstream(用于向文件中写入数据)和fstream(用于同时读取和写入文件)。这些文件流类提供了一组成员函数,可以用来打开、关闭、读取和写入文件。使用文件流可以方便地进行文件操作,如读取文件内容、写入数据到文件中等。这里我们主要学习文件的处理方法,想要深度了解文件流的小伙伴可以在学完本节之后再补充相关知识。

1.文本的写入及读取

字符串文件是C++经常处理的一种文件类型,其依赖为i/ostream和fstream类。

文本文件写入

我们看一个向文件中写入内容的例子:

#include<stdio.h>

#include<iostream>
#include<fstream>

#include <string>
using std::string;
using namespace std;
int main()
{
    string filename="test.txt"; // 文件名
    ofstream mytest; // 使用ofstream创建文件输出流对象,名字自拟
    mytest.open(filename); // 打开文件
    // 向文件中写入数据
    mytest<<"这是一个测试\n"<<"我们尝试连续输入内容\n";
    mytest<<"继续测试";
    // 关闭文件
    mytest.close();
}

在这段代码中,filename定义了一个文件名,我们尝试使用文件流打开文件,当当前路径下存在文件时,这段代码会截断文件,即打开文件后删除文件内容,重新进行写入操作,当文件不存在时,会在当前路径下创建文件并写入内容。运行这段代码会在.cpp文件路径下产生一个.txt文件:
在这里插入图片描述
虽然操作成功了,但是这样的做法存在不足和风险,比如我们在打开或创建文件时应当给出文件的确切位置,不应该只让它生成在.cpp文件的路径下;在使用文件之前应当判断文件是否成功打开。
为了解决以上不足,我们先详细了解一下ofstream输出流。ofstream创建了文件输出流对象,而open函数可以带有两个参数,即文件及路径和打开方式。文件的绝对路径有以下写法:

R"(C:\data…\test.txt)" (C++11标准)
“C:\data\…\text.txt”
“C:/data/…/text.txt”

其次,文件的打开方式可以这样规定:

ios::out 截断文件内容打开文件,为参数默认值
ios::truck 截断文件内容,类似于ios::out
ios::app 在文件后添加内容

我们再来测试一下:

int main()
{
    ofstream mytest;
    mytest.open("E:\\c++\\class3start11\\test.txt",ios::app);
    // 使用ios::app 在文件后添加内容
    // 向文件中写入数据
    mytest<<"这是一个测试\n"<<"我们尝试连续输入内容\n";
    // 关闭文件
    mytest.close();
}

再打开文件其内容就变成了:
在这里插入图片描述
此外,文件也不是一定能打开文件的情况,通常情况下无法正常打开文件的情况有:

1.目录不存在
2.磁盘空间已满
3.没有权限(linux系统下常见)

应对这种情况,我们可以使用mytest.is_open()来判断文件是否成功打开:

int main()
{
    ofstream mytest("test.txt",ios::app); // 在创建文件输出流对象时直接提供路径和打开方式参数,
                                          // 不需要再使用open进行打开
    if(mytest.is_open()) // 判断文件是否成功打开
    {
        mytest<<"这是一个测试\n"<<"我们尝试连续输入内容\n";
        // 关闭文件
        mytest.close();
        return 0;
    }
    else
    {
        cout<<"打开文件失败"<<endl;
        return 0;
    }
}

作为演示内容,我们就不写完整路径了。

文本文件读取

读取文本文件内容需要用ifstream输出流进行操作,其参数也是两个,文件名和打开方式。打开方式只能使用使用in:

int main()
{
    // 读取文件参数只有iOS::in
    ifstream mytest("test.txt",ios::in); // 用输入流打开文件,读取文件内容
    if(mytest.is_open())
    {
        cout<<"打开文件成功"<<endl;
        return 0;
    }
}

而后就要读取文件内容了。读取文件内容使用函数getline。getline函数有两个参数,即输出流对象和用于存储读取信息的变量。getline会按行读取文件内容,并返回是否读取成功。它很多重载,但常用的主要有两种方式:

if(mytest.is_open())
{
    string out; // 定义字符串类型out用于接收文件内容
    while(getline(mytest,out)) // 将当前行内容存入out,当前行没有内容时返回值为false
    {
        cout<<out<<endl;  
    }
    // 关闭文件
    mytest.close();
}
else
{
	cout<<"打开文件失败!"<<endl;
}

这样就可以在终端看到执行效果:
在这里插入图片描述
当然,这种用法还有一种比较简单的变种:

int main()
{
    // 读取文件参数只有iOS::in
    ifstream mytest("test.txt",ios::in);
    // 打开文件失败的原因:1.文件不存在2.目录不存在3.没有权限
    if(mytest.is_open())
    {
        string out;
	    while(mytest>>out)
	    {
	        cout<<out<<endl;  
	    }
	    // 关闭文件
	    mytest.close();
    }
    else
    {
		cout<<"打开文件失败"<<endl;
        return 0;
	}
}

这种方式使用起来更简单,我们记住就好。
另外,使用C风格字符串也可以接收文件内容,需要用到另一个getline函数的重载:

int main()
{
    ifstream mytest; 
    mytest.open("test.txt",ios::in)
    if(mytest.is_open())
    {
        char out[21]; // 三个字符存储一个汉字
        // 读取文件一般要用getline函数一行一行读
        while(mytest.getline(out,20)) // getline的一个重载,第一个参数为记录文件内容的字符串名,第二个参数是这个字符串最大下标
        // 如果字符数组不能够存下某行数据,会在对应处直接终止运行退出程序。
        {
            cout<<out<<endl;
        }
    }
    else
    {
        cout<<"打开文件失败"<<endl;
        return 0;
    }
    // 关闭文件
    mytest.close();
}

这个例子中,我们使用的C类型字符串最多可以存储的汉字只有7个,当遇到一行超过7个汉字的情况,会立刻终止运行,但不会报错。如果我们扩大数组的大小(由于换行符的存在,这里至少需要设置成31)就可以完整读取了。但实际中如果遇到这种情况并不好处理,在不知道文本内容的时候,设置足够大的字符数组较难做到,况且如果字符数组设置过大,又会浪费空间,因此这种用法并不推荐。

2.二进制文件的写入及读取

文本文件的读写方便实用,其特点为每个字符都有实际意义,但只能用于处理字符串类型。在实际使用中,很多时候我们需要存取更复杂的类型,比如结构体、整形、图片等,这些内容用字符串处理并不方便。计算机的世界里,只有0和1两个数字,任何数据本质上都是由二进制数描述的,因此如果我们使用二进制对文件进行存取,理论上就可以处理所有文件和数据。C++也为我们提供了这样的存取方法。

二进制文件写入

使用二进制处理文件首先也是要用ofstream创建输出流对象,打开文件时也要额外说明使用二进制方式打开。写入的过程需要使用write函数,具体使用方法示例如下:

// 定义一个需要记录数据的基本结构,也可以使用自定义类或C++基本数据类型
struct Student
{
    char name[32];
    int age;
    char sex;
};
int main()
{
    ofstream mytest("test.doc",ios::binary);
    // 需要再打开方式后面加上binary用于告诉计算机使用二进制方式打开
    // 这里的ios::out可以省略
    if(mytest.is_open())
    {
        Student child={"ZhangSan",15,'m'}; // 
        // 写入文件需要使用write函数
        mytest.write((const char*)&child,sizeof(Student));
        child=Student{"LiSi",20,'m'}; // 重载child,因为child变量之前已经赋值,因此不能直接初始化
        mytest.write((const char*)&child,sizeof(Student)); // 参数为需写入内容的地址(C++要求使用const char*),需写入内容的大小
        
    }
    else
    {
        cout<<"打开文件失败"<<endl;
        return 0;
    }
    // 关闭文件
    mytest.close();
}

这样我们就可以得到一个doc文件了:
在这里插入图片描述
但是它的内容是乱码的,这是因为二进制存储文件是按字节有效的,如果我们不知道存储的方式,是不能够正确解码的。

二进制文件读取

当我们知道数据的具体存储方式时,就可以编写程序查看存储的实际内容了。上例中,我们知道test.doc文件存储的数据是Student结构体,也就可以对它进行解码并查看内容了:

int main()
{
    ifstream mytest("test.doc",ios::in|ios::binary); // 读取二进制文件
    if(mytest.is_open())
    {
        // 二进制文件打开后需要用正确的接收格式接收
        Student child;
        // 二进制文件以数据类型的方式组织数据,没有换行的说法
        // mytest.read((char*)&ZhangSan,sizeof(Student)) 一次只能读取一个结构体数据
        while(mytest.read((char*)&child,sizeof(Student)))
        {
            cout<<child.name<<" "<<child.age<<" "<<child.sex<<endl;
        }
    }
    else
    {
        cout<<"打开文件失败"<<endl;
        return 0;
    }
    
    // 关闭文件
    mytest.close();
}
// 输出为:ZhangSan 15 m
//        LiSi 20 m

这里需要注意几点问题:
1.由于C++中string类型内存布局具有不确定性,因此可能会影响二进制文件的读取,建议使用字符数组存储字符串;
2.一个结构体变量只能初始化一次,想要修改变量内容可以使用赋值或重载的方式;
3.C++处理文本文件时以换行符作为读取内容分隔符,getline函数也是在读取到第一个换行符时返回。二进制文件中换行符只被视为二进制数据,文件读取时以数据块作为分隔。

3.小结

这节主要介绍了C++处理文本文件和二进制文件的部分方法,由于篇幅原因,我们只提到了较为常见的函数和用法。后面的学习中我会继续对文件操作进行补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1421638.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

洛谷P8599 [蓝桥杯 2013 省 B] 带分数

[蓝桥杯 2013 省 B] 带分数 题目描述 100 100 100 可以表示为带分数的形式&#xff1a; 100 3 69258 714 100 3 \frac{69258}{714} 100371469258​。 还可以表示为&#xff1a; 100 82 3546 197 100 82 \frac{3546}{197} 100821973546​。 注意特征&#xff1a;带分…

ASTORS国土安全奖:ManageEngine AD360荣获银奖

美国安全今日&#xff08;AST&#xff09;的年度“ASTORS”国土安全奖计划是一个备受瞩目的活动&#xff0c;致力于突显国土安全领域的创新与进步。这一奖项旨在表彰在保护国家免受安全威胁方面做出卓越贡献的个人和组织。该计划汇聚了执法、公共安全和行业领袖&#xff0c;不仅…

【Web前端实操20】商城官网_黑色导航

今天继续着上一篇博客的内容进行编写,本次主要实现的是商场官网实战里面的黑色导航栏部分,也就是广告图片下面的部分。 本次除了每篇都要通用的样式CSS代码之外,还增添了一个引用矢量图标的样式,如果有兴趣的友友们,可以看看我的这篇博客,上面详细介绍了如何下载矢量图标…

live2D学习:做好让图片动起来的准备

做好让图片动起来的准备https://www.bilibili.com/video/BV1JE411Y7Te?p2&vd_source124076d7d88eee393a1d8bf6fc787efa 把psd文件通过菜单栏的“打开文件”进行导入或直接把psd文件拖到Live2D Cubism Editor 4.0的面板中 网格 我们在点击图像的一部分时&#xff0c;会出现…

Boosting semantic human matting with coarse annotations

前向推理在modelscope中开源了&#xff0c;但是训练没开源&#xff0c;且是基于TensorFlow的&#xff0c;复现起来是比较麻烦的。 1.Introduction 分割技术主要集中在像素级二元分类&#xff0c;抠图被建模为前景图像F和背景图像B的加权融合&#xff0c;大多数matte方法采用指…

RK3568平台 热插拔机制

一.热插拔的基本概念 热插拔是指在设备运行的情况下&#xff0c;能够安全地插入或拔出硬件设备&#xff0c;而无需关闭或重启系统。这意味着你可以在计算机或其他电子设备上插入或拔出硬件组件&#xff08;比如USB设备&#xff0c;扩展卡&#xff0c;硬件驱动器等&#xff09;…

001集—shapefile(.shp)格式详解——arcgis

一、什么是shapefile Shapefile 是一种用于存储地理要素的几何位置和属性信息的非拓扑简单格式。shapefile 中的地理要素可通过点、线或面&#xff08;区域&#xff09;来表示。包含 shapefile 的工作空间还可以包含 dBASE 表&#xff0c;它们用于存储可连接到 shapefile 的要…

mysql入门到精通003-基础篇-SQL

1、目录 2、SQL通用语法及分类 2.1 SQL通用语法 2.2 SQL分类 3、SQL DDL数据库操作 3.1 SQL DDL表操作-创建&查询 3.1.1 表操作-查询 3.1.2 表操作-创建 create table tb_user(id int comment 编号,name varchar(50) comment 用户名,age int comment 用户名,gender varch…

MySQL库表操作 作业

题目&#xff1a; 1. sql语句分为几类?2. 表的约束有哪些,分别是什么,设置的语法分别是什么?3. 做出班级表,学生表的E-R图,数据库模型图,以及核心的sql语句. 1. MySQL致力于支持全套ANSI/ISO SQL标准。在MySQL数据库中&#xff0c;SQL语句主要可以划分为以下几类: > DD…

搜索引擎评价指标及指标间的关系

目录 二分类模型的评价指标准确率(Accuracy,ACC)精确率(Precision,P)——预测为正的样本召回率(Recall,R)——正样本注意事项 P和R的关系——成反比F值F1值F值和F1值的关系 ROC&#xff08;Receiver Operating Characteristic&#xff09;——衡量分类器性能的工具AUC&#xff…

OpenCV 2 - 矩阵的掩膜操作

1知识点 1-1 CV_Assert(myImage.depth() == CV_8U); 确保输入图像是无符号字符类型,若该函数括号内的表达式为false,则会抛出一个错误。 1-2 Mat.ptr(int i = 0); 获取像素矩阵的指针,索引 i 表示第几行,从0开始计行数。 1-3 const uchar* current = mylmage.ptr(row); 获得…

Physically Based Area Lights

11.1 概括 本章介绍了由 Guerrilla Games 公司在 PS4 开发的基于物理的区域照明系统&#xff08;见图11.1&#xff09;。 我们提出了一种新颖、实时的区域照明分析模型&#xff0c;能够支持多种照明形状。每种形状都可以用平面上简单的三维或二维函数来表示。讨论的应用包括以下…

Apache Flink文件上传漏洞(CVE-2020-17518)漏洞代码分析

漏洞复现参考如下文章 Apache Flink文件上传漏洞&#xff08;CVE-2020-17518&#xff09;漏洞复现分析_文件上传漏洞复现cve-CSDN博客 分析代码的话&#xff0c;首先找到漏洞修复的邮件 漏洞详情&#xff0c;可以看到漏洞概要&#xff0c;影响的版本&#xff0c;漏洞描述以及…

Docker核心教程

1. 概述 官网&#xff1a;https://docs.docker.com/ Docker Hub 网站&#xff1a;https://hub.docker.com/ 容器较为官方的解释&#xff1a; 一句话概括容器&#xff1a;容器就是将软件打包成标准化单元&#xff0c;以用于开发、交付和部署。 容器镜像是轻量的、可执行的独立…

嵌入式学习第十四天!(结构体、共用体、枚举、位运算)

1. 结构体&#xff1a; 1. 结构体类型定义&#xff1a; 嵌入式学习第十三天&#xff01;&#xff08;const指针、函数指针和指针函数、构造数据类型&#xff09;-CSDN博客 2. 结构体变量的定义&#xff1a; 嵌入式学习第十三天&#xff01;&#xff08;const指针、函数指针和…

Meta开源Code Llama 70B,缩小与GPT-4之间的技术鸿沟

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【C++基础入门】一、C++初识

一、C初识 1.1 第一个C程序 编写一个C程序总共分为4个步骤 创建项目创建文件编写代码运行程序 1.1.1 创建项目 ​ Visual Studio是我们用来编写C程序的主要工具&#xff0c;我们先将它打开 1.1.2 创建文件 右键源文件&#xff0c;选择添加->新建项 给C文件起个名称&am…

vue3-hand-mobile

当我写完手势移动事件后&#xff0c;我又通过svg的方法添加了一段文字和polygon。当我在这个蓝色的polygon上滑动手势的时候&#xff0c;会报错。 可能这个bug只是我个人的代码导致的。但是我觉得vue3-hand-mobile插件的这一段代码写的有问题。 我通过circular-json库修复了这…

petalinux2022.2启动文件编译配置

安装必要运行库: sudo apt-get install iproute2 gawk python3 python sudo apt-get install build-essential gcc git make net-tools libncurses5-dev tftpd sudo apt-get install zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget git-core diffstat sudo apt-ge…

IDEA Java常用快捷键

目录 main方法快捷键&#xff1a;psvm输出语句&#xff1a;sout复制行&#xff1a;ctrld删除行&#xff1a;ctrly单行注释或多行注释 &#xff1a; Ctrl / 或 Ctrl Shift /for循环 直接 &#xff1a;fori代码块包围&#xff1a;try-catch,if,while等 ctrlaltt缩进&#xff1…