首页 > 编程语言 >C++文件操作-随机存取&&缓冲区及流状态

C++文件操作-随机存取&&缓冲区及流状态

时间:2025-01-17 12:29:28浏览次数:3  
标签:std 文件 随机存取 ios C++ && 缓冲区 fin 指针

目录

文件操作-随机存取

1.fstream类

2.文件的位置指针

3.随机存取

文件操作-缓冲区及流状态

1.文件缓冲区

2.流状态


文件操作-随机存取

1.fstream

fstream类既可以读文本/二进制文件,也可以写文本/二进制文件。

fstream类的缺省模式是ios::in | ios::out如果文件不存在,以只写模式打开(ios::out)可以创建文件,以读/写或只读模式不能创建空文件.缺省模式下打开文件不会截断文件,但仍会从头开始写/读,再加上|ios::trunc就会截断文件,以只写方式打开文件也会截断文件.只写方式下用输入流读取文件内容,编译不会报错,但是实际运行读取不出内容.

普遍的做法是:

1)如果只想写入数据,用ofstream;如果只想读取数据,用ifstream;如果想写和读数据,用fstream,这种情况不多见。不同的类体现不同的语义。

2)在Linux平台下,文件的写和读有严格的权限控制。(需要的权限越少越好)

2.文件的位置指针

对文件进行读/写操作时,文件的位置指针指向当前文件读/写的位置。

很多资料用“文件读指针的位置”和“文件写指针的位置”,容易误导人。不管用哪个类操作文件,文件的位置指针只有一个。

1)获取文件位置指针

ofstream类的成员函数是tellp();ifstream类的成员函数是tellg();fstream类两个都有,效果相同。

std::streampos tellp();

std::streampos tellg();

2)移动文件位置指针

ofstream类的函数是seekp();ifstream类的函数是seekg();fstream类两个都有,效果相同。

方法一:

std::istream & seekg(std::streampos _Pos);  

fin.seekg(128);   // 把文件指针移到第128字节。

fin.seekp(128);   // 把文件指针移到第128字节。

fin.seekg(ios::beg) // 把文件指针移动文件的开始。

fin.seekp(ios::end) // 把文件指针移动文件的结尾。

方法二:

std::istream & seekg(std::streamoff _Off,std::ios::seekdir _Way);

在ios中定义的枚举类型:

enum seek_dir {beg, cur, end};  // beg-文件的起始位置;cur-文件的当前位置;end-文件的结尾位置。

fin.seekg(30, ios::beg);    // 从文件开始的位置往后移30字节。

fin.seekg(-5, ios::cur);     // 从当前位置往前移5字节。

fin.seekg( 8, ios::cur);     // 从当前位置往后移8字节。

fin.seekg(-10, ios::end);   // 从文件结尾的位置往前移10字节。

3.随机存取

随机存取是指直接移动文件的位置指针,在指定位置读取/写入数据。

代码示例:

#include <iostream>

#include <fstream>  // fstream类需要包含的头文件。

using  namespace std;

int main()

{

	string filename = R"(D:\CODE\Demo\test.txt)";

	fstream fs;

	fs.open(filename,ios::in|ios::out);

	if (fs.is_open() == false)

	{

		cout << "打开文件" << filename << "失败。\n";  return 0;

	}

	fs << "我是星穹铁道高手.\n";

	fs.seekp(0);    // 把文件位置指针移动到第0字节处。

	string buffer;
	while (fs >> buffer)
	{
	cout << buffer << endl;
	}

	fs.close();    // 关闭文件,fs对象失效前会自动调用close()。

	cout << "操作文件完成。\n";

}

注:若是写后未重置文件位置指针就直接读取,会产生一些意料之外的结果(我也不知道为什么),可能是缓冲区或者读空文件的原因???问题如下图:占用空间本来应该是19字节(Windows系统下,linux则是18字节),但是却文件大小却变成了4KB,占用空间达到8KB,很奇怪,有大佬知道吗?

文件操作-打开文件的模式(方式)

ios::out      1)会截断文件(即清空原文件数据但不删除原文件,从头开始写);2)可以用seekp()移动文件指针。

ios:trunc   1)会截断文件;2)可以用seekp()移动文件指针。

ios::app    1)不会截断文件;2)文件指针始终在文件未尾,不能用seekp()移动文件指针。

ios::ate    打开文件时文件指针指向文件末尾,但是,可以在文件中的任何地方写数据(可移动指针)。

ios::in         打开文件进行读操作,即读取文件中的数据。

ios::binary        打开文件为二进制文件,否则为文本文件。

注:ate是at end的缩写,trunc是truncate(截断)的缩写,app是append(追加)的缩写。

文件操作-缓冲区及流状态

1.文件缓冲区

文件缓冲区(缓存)是系统预留的内存空间,用于存放输入或输出的数据。

根据输出和输入流,分为输出缓冲区和输入缓冲区。

注意,在C++中,每打开一个文件,系统就会为它分配缓冲区。不同的流,缓冲区是独立的

程序员不用关心输入缓冲区,只关心输出缓冲区就行了。

在缺省模式下,输出缓冲区中的数据满了才把数据写入磁盘,但是,这种模式不一定能满足业务的需求。

输出缓冲区的操作:

1)flush()成员函数

刷新缓冲区,把缓冲区中的内容写入磁盘文件。

2)endl

换行,然后刷新缓冲区(两种功能),而\n无刷新缓冲区功能。

3)unitbuf

fout << unitbuf;

设置fout输出流,在每次操作之后自动刷新缓冲区。

4)nounitbuf

fout << nounitbuf;

设置fout输出流,让fout回到缺省的缓冲方式。

2.流状态

流状态有三个:eofbit、badbit和failbit,取值:1-设置;或0-清除。

当三个流状成都为0时,表示一切顺利,good()成员函数返回true。

1)eofbit

当输入流操作到达文件未尾时,将设置eofbit。

eof()成员函数检查流是否设置了eofbit。

2)badbit

无法诊断的失败破坏流时,将设置badbit。(例如:对输入流进行写入;磁盘没有剩余空间)。

bad()成员函数检查流是否设置了badbit。

3)failbit

当输入流操作未能读取预期的字符时,将设置failbit(非致命错误,可挽回,一般是软件错误,例如:想读取一个整数,但内容是一个字符串;文件到了未尾)I/O失败也可能设置failbit。

fail()成员函数检查流是否设置了failbit(是否为1)。

4)clear()成员函数清理流状态(全部清零)。

5)setstate()成员函数重置流状态

代码示例1:可在Linux系统下调用,跟踪查看文件信息,知晓缓冲区运行原理

#include <iostream>

#include <fstream>          // ofstream类需要包含的头文件。

#include <unistd.h>

using  namespace std;

int main()

{

  ofstream fout("/oracle/tmp/bbb.txt");   // 打开文件。

  fout << unitbuf;

  for (int ii = 0; ii < 1000; ii++)  // 循环1000次。

  {

    fout << "ii=" << ii << ",我是星穹铁道高高高高高高高高高高高高高手。\n";

    //fout.flush();      // 刷新缓冲区。

    usleep(100000);    // 睡眠十分之一秒。

  }

  fout.close();  // 关闭文件。

}

代码示例2:

#include <iostream>

#include <fstream>  // ifstream类需要包含的头文件。

#include <string>     // getline()函数需要包含的头文件。

using  namespace std;

int main()

{

ifstream fin(R"(D:\data\txt\test.txt)", ios::in);

if (fin.is_open() == false) {

cout << "打开文件" << R"(D:\data\txt\test.txt)" << "失败。\n";  return 0;

}

string buffer;

/*while (fin >> buffer) {

cout << buffer << endl;

}*/

while (true) {

fin >> buffer;

cout << "eof()=" << fin.eof() << ",good() = " << fin.good() << ", bad() = " << fin.bad() << ", fail() = " << fin.fail() << endl;

if (fin.eof() == true) break;

cout << buffer << endl;

}

fin.close();    // 关闭文件,fin对象失效前会自动调用close()。

}

注:此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记及交流学习使用。 

标签:std,文件,随机存取,ios,C++,&&,缓冲区,fin,指针
From: https://blog.csdn.net/qq_74224788/article/details/145112861

相关文章

  • 【C++】IO流
    ......
  • 【c++】【Linux】内存碎片
    【c++】【Linux】内存碎片内碎片分配给进程未被使用的部分当内存被分配给某个进程时,分配的内存块可能比实际需求稍大,未被使用的部分称为内碎片。例如,如果需要3.6k内存此时根据buddy伙伴系统内存分配方式最少分配4k为一页那其中0.4k未被使用的内存就是内碎片如果使......
  • C++ 面向对象(构造 & 析构函数)
    二、构造&析构函数2.1构造和析构2.1.1功能构造函数功能构造函数在类实例化对象时用于完成对象成员的初始化,通常包括以下操作:   1.为成员变量分配内存空间   2.初始化成员变量   3.执行类似打开文件、分配资源等额外操作析构函数功能主要作用......
  • 【C++】类与对象(中上)(难点部分)
    目录 ......
  • 在C++中std::string 和string有啥区别呀?
    在C++中,std::string和string实际上是同一个类型,只是它们的命名空间(namespace)不同。具体来说:(我说为啥在写代码的时候都有个usingnamespacestd;语句我还以为是闹着玩.)std::string明确指定了string类型位于std命名空间中。string是std::string的简写,但要使......
  • 探讨c++内存布局背后的原因以及策略
    内存布局通常是按照成员变量的声明顺序,但由于对齐和填充的影响,编译器可能会调整成员变量的顺序。改变顺序的主要目的是为了优化内存使用和提高访问效率。以下是一些具体原因:1.提高内存访问效率对齐要求:不同数据类型有不同的对齐要求。将对齐要求相同或相近的成员变量放......
  • C++中线程同步与互斥的四种方式介绍及对比详解
    引言在C++中,当两个或更多的线程需要访问共享数据时,就会出现线程安全问题。这是因为,如果没有适当的同步机制,一个线程可能在另一个线程还没有完成对数据的修改就开始访问数据,这将导致数据的不一致性和程序的不可预测性。为了解决这个问题,C++提供了多种线程同步和互斥的机制。互斥......
  • C++ open()和read()函数使用详解
    对于Framework工程师来说,必要C或者C++编程能力是必须的,像对设备节点的操作是最基本的操作,那么我们便会用到open和read函数。open()函数用于打开文件,而read()函数用于从打开的文件中读取数据。open()函数open()函数是C/C++标准库中的一个POSIX标准函数,用于打开一个文件并返回......
  • 深入理解C++ 空类大小
    在C++中,规定空类(即类中没有任何数据成员、成员函数、虚函数等成员的类)的大小为1字节,这背后主要有以下几方面的原因:保证对象的唯一性和可区分性在C++的面向对象编程模型中,对象是类的实例化结果,每个对象在内存中都需要占据一定的空间,以便程序能够通过地址等方式对其进行操作和区......
  • C++17 Filesystem 实用教程
    C++17标准带来了std::filesystem库,提供了强大的工具来处理文件路径,目录以及其他与文件系统相关的操作.这篇文章适合C++初学者以及希望掌握C++17新特性的开发者,旨在帮助他们高效地完成文件系统相关任务.什么是std::filesystem?std::filesystem是C++标准库的一部......