C++文件的读取详解,以及使用eof出现末行数据被读取两次情况

2023-10-31

目录

0.前言

对文件流的读写

文件打开方式:

1.写文本文件

2.读文本文档

2.1使用efo函数判断出现数据被读取两次

3.二进制方式写文件

4.二进制读文件

 5.按指定格式读写数据stringstream


0.前言

对文件流的读写

   ifstream    对文件输入(读文件)

   ofstream    对文件输出(写文件)

   fstream     对文件输入或输出

文件打开方式:

ios::in

读方式打开文件

ios::out

写方式打开文件

ios::trunc

如果此文件已经存在, 就会打开文件之前把文件长度截断为0

ios::app

尾部最加方式(在尾部写入)

ios::ate

文件打开后, 定位到文件尾   

ios::binary

二进制方式(默认是文本方式)

 以上打开方式, 可以使用位操作 |  组合起来。

1.写文本文件

#include<iostream>
#include<fstream>
#include<sstream>
using namespace std;


int main() {

	ofstream ofs;   //也可以使用fstream ,但是fstream默认打开方式不截断文件长度

    //ofstream 的默认打开方式是截断式写入   ios::out|ios::trunc
    //fstream 的默认打开方式是截断写入   ios::out
    //建议指定打开方式
	ofs.open("temp.txt",ios::out|ios::trunc);
	string name;
	int age;
	while (1) {
		cout << "请输入姓名([ctrl]+z退出):" ;
		cin >> name;
		if (cin.eof()) {
			break;
		}
		cout << "请输入年龄:" ;
		cin >> age;
		stringstream s;
		s << name << '\t' << age<<'\n';
		ofs << s.str();
	}
	ofs.close();




	system("pause");
	return 0;
}

运行截图:

  打开temp.txt文档:

2.读文本文档

#include<iostream>
#include<fstream>
#include<sstream>
using namespace std;


int main() {

	ifstream ifs;
	ifs.open("temp.txt");
	string name;
	int age;
	while (1) {
		if (ifs.eof()) {
			break;
		}
		ifs >> name;
		ifs>> age;
		cout << name << '\t' << age << endl;
	}
	ifs.close();
	cout << line << endl;
	system("pause");
	return 0;
}

运行结果:


 

由运行结果可知,文档的最后一行元素被读取两次,这是为什么呢?

2.1使用efo函数判断出现数据被读取两次

在使用C/C++读文件的时候,一定都使用过eof()这个函数来判断文件是否为空或者是否读到文件结尾了,大家可能有一个误区,认为eof()返回true时是读到文件的最后一个字符,其实不然,eof()返回true时是读到文件结束符0xFF,而文件结束符是最后一个字符的下一个字符。

 这就是在判断文档是否为空时要先用char读取,再使用eof函数。

解决方法:
1.提前读取,再进行判断(注意要使用string类型读取)

#include<iostream>
#include<fstream>
#include<sstream>
using namespace std;


int main() {
	ifstream ifs;
	ifs.open("temp.txt");
	string name;
	int age;
	int line = 0;
	while (1) {
		ifs >> name;
		if (ifs.eof()) {
			break;
		}
		ifs>> age;
		cout << name << '\t' << age << endl;
	}
	ifs.close();
	system("pause");
	return 0;
}

 运行结果:

3.二进制方式写文件

#include<fstream>
#include<iostream>
using namespace std;

int main()
{
	string name ;
	int age ;
	ofstream ofs;
	//.dat文件用记事本打开会是乱码
	ofs.open("user.dat", ios::out | ios::trunc | ios::binary);

	while (1) {
		cout << "请输入姓名([ctrl]+z退出):";
		cin >> name;
		if (cin.eof()) {
			break;
		}
		cout << "请输入年龄:";
		cin >> age;
		ofs << name << "\t";
		//outfile << age << endl;  //会自动转成文本(字符串)方式写入

		ofs.write((char*)&age, sizeof(age)); //将age的地址转为char指针类型
	}
	ofs.close();



	// 关闭打开的文件
	ofs.close();

	system("pause");
	return 0;
}

 使用notepad++查看运行后的二进制文件:

4.二进制读文件

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string name;
	int age;

    //ifs>>age;  temp是二进制存储,直接读取会以文本方式读出
    //使用read读取会读取空格符\制表符.....
    //ifs.read((char*)&age,sizeof(age));   
	ifstream ifs;
	ifs.open("user.dat", ios::in | ios::binary);
	while (1) {
		ifs >> name;
		if (ifs.eof()) { //判断文件是否结束
			break;
		}
		cout << name << "\t";

		// 跳过中间的制表符
		char tmp;
		ifs.read(&tmp, sizeof(tmp));

		//infile >> age; //从文本文件中读取整数, 使用这个方式
		ifs.read((char*)&age, sizeof(age));
		cout << age << endl;  //文本文件写入
	}

	// 关闭打开的文件
	ifs.close();

	system("pause");
	return 0;
}

运行结果:

 5.按指定格式读写数据stringstream

#include<fstream>
#include<string>
#include<iostream>
#include<sstream>
using namespace std;

//按指定格式写文件
void funWrite() {
    string name = "凌云志";
    int age =18;
    ofstream ofs;
    ofs.open("temp.txt");
    stringstream s;
    s << "姓名:" << name << "\t\t年龄:" << age << endl;

    //把指定格式数据写入文件
    ofs << s.str();

    ofs.close();

}

//按指定格式读文件
void funRead() {
    ifstream ifs;
    ifs.open("temp.txt");
    string line;

    char name[32];
    int age;
    while (1) {
        getline(ifs, line);     //每次读取一行
        if (ifs.eof()) { break; }
        //按C语言格式将读取的一行转为char*数组格式(line.c_str())
        //注意文档中的“:”冒号是中文还是英文
        sscanf_s(line.c_str(), "姓名:%s 年龄:%d", name, sizeof(name), &age);
        cout << "姓名:" << name << "\t\t年龄:" << age << endl;
    }
    ifs.close();
}

int main() {



    funWrite();
    funRead();
    system("pause");
    return 0;

}

运行结果以及文档截图:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++文件的读取详解,以及使用eof出现末行数据被读取两次情况 的相关文章

  • 删除文件的最后 10 个字符

    我想删除文件的最后 10 个字符 说一个字符串 hello i am a c learner 是文件内的数据 我只是希望该文件是 hello i am a 文件的最后 10 个字符 即字符串 c learner 应在文件内消除 解决方案 将
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include

随机推荐

  • springboot+mybatis+druid+postgreSql案例

    springboot mybatis druid postgreSql mysql 示例 springboot mybatis druid postgreSql mysql 示例 简介 结构解析 代码剖析 entity层 Dao层 serv
  • Java-System、Math、BigInteger、BigDecimal常用类的使用

    Java System Math BigInteger BigDecimal常用类的使用 1 System类 System类代表系统 系统级的很多属性和控制方法都放置在该类的内部 该类位于java lang包 由于该类的构造器是privat
  • 解决Linux7 ping出现 未知的名称或服务 错误

    问题描述 Linux7在利用命令nmtui进入图形化界面配置Linux的网络后为测试是否成功联网 ping配置的IP成功但ping如www baidu com常见网站时出现 gt ping www baidu com 未知的名称或服务 解决
  • 网络编程知识预备(5) ——libcurl库安装及其编程访问百度首页(断点续传)

    本文为学习笔记 整合课程内容以及下列文章 其中 libcurl函数库常用字段解读部分 参考博文 原文地址 作者 冬冬他哥哥 目录 Libcurl库简介 Libcurl等三方库的通用编译方法 三方库使用前通读方法 库的配置 编译 安装 调用l
  • protobuf生成prototxt文件

    使用protobuf可以分为以下几步 1 proto文件的定义 在这个文件中定义了最终生成的prototxt格式 举个例子如下所示 syntax proto2 package label proto message DetectLabel
  • scrapy缺点

    Scrapy 是一个功能强大的网络爬虫框架 但也有一些缺点 Scrapy 只能爬取静态网页 无法爬取动态网页 Scrapy 只能爬取一个网站的数据 无法爬取多个网站的数据 Scrapy 需要编写代码 对于那些不会编写代码的人来说可能会有些困
  • LiteOS内存管理

    1 内存管理简介 内存管理模块管理系统的内存资源 它是操作系统的核心模块之一 主要包括内存的初始化 分配以及释放 在系统运行过程中 内存管理模块通过对内存的申请 释放操作 来管理用户和OS对内存的使用 使内存的利用率和使用效率达到最优 同时
  • obs无法连接服务器?PotPlayer获取不到视频

    搭建基于nginx的rtmp直播服务器 https hywlovexyc info blog archives 572 rtmp server listen 1935 监听的端口 chunk size 4000 application yu
  • 删除中间节点

    题目 若链表中的某个节点 既不是链表头节点 也不是链表尾节点 则称其为该链表的 中间节点 假定已知链表的某一个中间节点 请实现一种算法 将该节点从链表中删除 例如 传入节点 c 位于单向链表 a gt b gt c gt d gt e gt
  • sqlserver查看数据表结构

    可以通过两种方式 1 sp help 表名 2 sp columns 表名
  • 我的世界服务器config文档,Essentials/配置文件/config.yml

    ops name color none nickname prefix max nick length 15 change displayname true change playerlist true add prefix suffix
  • Unity--虚拟轴

    1 查看虚拟轴 Edit gt project settings gt Input 2 获取虚拟轴 input GetAxis 用法 GetAxis Mouse X GetAxis Mouse Y GetAxis Mouse ScrollW
  • centos7Linux中的lvm、pv、vg、lv,以及Linux扩容,创建新分区

    概念 本着言简意赅的目的 以下概念会在扩容时用到 需熟知 不然会不理解具体操作在干什么 lvm 逻辑卷管理器 Logical Volume Manager 它使系统管理员可以更方便的为应用与用户分配存储空间 在LVM管理下的存储卷可以按需要
  • QT信号槽原理(一)connect函数

    目录 2个类型和1个签名 Qt ConnectionType QMetaMethod MethodType 方法签名 connect函数源码解析 函数原型 第一步 参数检查 第二步 获取信号和槽的index 第三步 检查信号和槽的参数是否匹
  • Opencv之图像固定阈值二值化处理threshold

    目录 一 图像二值化 二 threshold 三 代码 一 图像二值化 定义 图像的二值化 就是将图像上的像素点的灰度值设置为0或255 也就是将整个图像呈现出明显的只有黑和白的视觉效果 灰度值0 黑 灰度值255 白 一幅图像包括目标物体
  • Cygwin编译JNI的环境配置

    一 什么是NDK NDK提供了一系列的工具 帮助开发者快速开发C 或C 的动态库 并能自动将so和java应用一起打包成apk 这些工具对开发者的帮助是巨大的 NDK 集成了交叉编译器 并提供了相应的mk文件隔离CPU 平台 ABI 等差异
  • MacBook怎么安装使用Windows软件和虚拟机?

    作为一名MacBook用户 你可能会发现有些软件和应用程序只适用于Windows操作系统 但别担心 今天我们将介绍两种方法 让你的MacBook轻松安装Windows软件和运行Windows虚拟机 为你的工作 学习和娱乐任务带来更多可能性
  • Vue 3 使用 vue-echarts 的柱状图 barItem 和 x, y 轴点击事件实现

    需求背景 最近使用 Vue 3 开发柱状图功能 图表已经绘制完成了 但是突然有需求加进来要可以点击柱状图的柱子 barItem 和 x y 轴的坐标 然后根据点击的位置 处理不同区域的点击事件 作为 CV 程序员 第一时间搜索网上的解决方案
  • 抖音养号步骤有哪些?最重要的3步你做到了吗?

    国仁网络资讯 为大家整理一份超详细的 短视频运营手册 回复私信限时免费领取 有人问我 新手养号怎么养 老账号养号要怎么养 其实 严格来说 养号不分新老 不管你是刚注册的抖音号 还是已经用过很久的抖音号 养号都是运营账号必做的事项之一 那么
  • C++文件的读取详解,以及使用eof出现末行数据被读取两次情况

    目录 0 前言 对文件流的读写 文件打开方式 1 写文本文件 2 读文本文档 2 1使用efo函数判断出现数据被读取两次 3 二进制方式写文件 4 二进制读文件 5 按指定格式读写数据stringstream 0 前言 对文件流的读写 if