当前位置: 首页 > article >正文

Linux C\C++编程-文件位置指针与读写文件数据块

【图书推荐】《Linux C与C++一线开发实践(第2版)》_linux c与c++一线开发实践pdf-CSDN博客

《Linux C与C++一线开发实践(第2版)(Linux技术丛书)》(朱文伟,李建英)【摘要 书评 试读】- 京东图书

LinuxC\C++编程技术_夏天又到了的博客-CSDN博客

4.9.7  文件位置指针

先复习一下C语言中的文件指针定位函数fseek(),其声明如下:

int fseek(FILE *fp, LONG offset, int origin);

其中,fp是文件指针;offset是相对于origin规定的偏移位置量;origin是指针移动的起始位置,可设置为以下3种情况:

  • SEEK_SET:文件开始位置。
  • SEEK_CUR:文件当前位置。
  • SEEK_END:文件结束位置。

当offset是向文件末尾方向偏移的时候,无论偏移量是否超出文件末尾,fseek都返回0,当偏移量没有超出文件末尾的时候,文件指针指向正常的偏移地址;当偏移量超出文件末尾的时候,文件指针指向文件末尾,并不会返回表示偏移出错的-1值。当offset向文件头方向偏移的时候,如果偏移量没有超出文件头,就是正常偏移,文件指针指向正确的偏移地址,fseek返回值为0;当偏移量超出文件头时,fseek返回-1值,文件指针不变,还是处于原来的地址。

在C++中,istream和ostream也提供了用于重新定位文件位置指针的成员函数seekg和seekp:seekg用于设置输入文件流的文件流指针位置,而seekp用于设置输出文件流的文件流指针位置。它们的声明如下:

ostream& seekp( streampos pos );

ostream& seekp( streamoff off, ios::seek_dir dir );

istream& seekg( streampos pos );

istream& seekg( streamoff off, ios::seek_dir dir );

其中,pos表示新的文件流指针位置值;off表示需要偏移的值;dir表示搜索的起始位置,该参数的类型是一个枚举:

enum seek_dir {beg, cur, end};

每个枚举常量的含义如下:

  • ios::beg:文件流的起始位置(默认值,从流的开头开始定位)。
  • ios::cur:文件流的当前位置。
  • ios::end:文件流的结束位置。

文件位置指针是一个整数值,指定了从文件的起始位置到指针所在位置的字节数。下面是关于定位文件位置指针的代码片段。

// 定位到 fileObject 的第 n 个字节(假设是 ios::beg)
fileObject.seekg( n );

// 把文件的读指针从 fileObject 当前位置向后移 n 个字节
fileObject.seekg( n, ios::cur );

// 把文件的读指针从 fileObject 末尾往回移 n 个字节
fileObject.seekg( n, ios::end );

// 定位到 fileObject 的末尾
fileObject.seekg( 0, ios::end );

下面的例子使用这些函数来获得一个二进制文件的大小。

【例4.14】获得二进制文件的大小

(1)打开Visual Studio Code,新建文本文件test.cpp,输入代码如下:

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

    
const char * filename = "afile.dat"; // afile.dat在前面的例子中已经生成了
    
int main() {
	long l, m;
	ifstream file(filename, ios::in | ios::binary);
	l = file.tellg();
	file.seekg(0, ios::end);
	m = file.tellg();
	file.close();
	cout << "size of " << filename;
	cout << " is " << (m - l) << " bytes.\n";
	return 0;
}

(2)上传test.cpp到Linux,在终端下输入命令g++ -o test test.cpp,然后运行test,运行结果如下:

# g++ -o test test.cpp

# ./test

size of afile.dat is 7 bytes.

假设当前目录下有一个文件afile.dat,大小为7字节,上面的代码就可以判断出其大小。同时,我们可以在命令行下验证一下:

# ll afile.dat

-rw-r--r-- 1 root root 7 3月  15 21:49 afile.da

可以看出,果然是7字节。

4.9.9  读写文件数据块

C++的I/O中提供了write和read函数,分别从流中读取数据和向流写入数据。write函数是ostream的一个成员函数,被ofstream继承。而read是istream的一个成员函数,被ifstream继承。类fstream的对象同时拥有这两个函数。Write和read函数的原型是:

ostream& write ( char * buffer, streamsize size );

istream read ( char * buffer, streamsize size );

这里buffer是一块内存的地址,用来存储要写入或读出的数据。参数size是一个整数值,表示要从buffer中读出或写入的字符数。

下面两个小例子演示了这两个函数的使用。

【例4.16】复制文件

(1)打开Visual Studio Code,新建文本文件test.cpp,输入代码如下:

// 复制文件
#include <fstream>      // std::ifstream, std::ofstream

int main() {
	std::ifstream infile("myfile.txt", std::ifstream::binary);
	std::ofstream outfile("new.txt", std::ofstream::binary);

	// 获取文件大小
	infile.seekg(0, infile.end);
	long size = infile.tellg();
	infile.seekg(0);

 	// 为文件内容分配内存
	char* buffer = new char[size];

	// 读取infile的内容
	infile.read(buffer, size);

	// 向outfile写入内容
	outfile.write(buffer, size);

	// 释放动态分配的内存
	delete[] buffer;

	outfile.close();
	infile.close();
	return 0;
}

(2)上传test.cpp到Linux,在终端下输入命令g++ -o test test.cpp,然后运行test,运行结果如下:

# g++ test.cpp -o test
# ./test
# cat new.txt
Linux
boy

例4.17】读取文件到内存

(1)打开Visual Studio Code,新建文本文件test.cpp,输入代码如下:

// 将文件读入内存
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main() {

	std::ifstream is("myfile.txt", std::ifstream::binary);
	if (is) {
	    // 获取文件长度
		is.seekg(0, is.end);
		int length = is.tellg();
		is.seekg(0, is.beg);

		char * buffer = new char[length];

		std::cout << "Reading " << length << " characters... ";
		// 以块的形式读取数据
		is.read(buffer, length);

		if (is)
			std::cout << "all characters read successfully.";
		else
			std::cout << "error: only " << is.gcount() << " could be read";
		is.close();

		// 缓冲区包含整个文件内容
		delete[] buffer;
	}
}

(2)上传test.cpp到Linux,在终端下输入命令g++ -o test test.cpp,然后运行test,运行结果如下:

# g++ test.cpp -o test

# ./test

Reading 18 characters... all characters read successfully.


http://www.kler.cn/a/514135.html

相关文章:

  • 汽车钥匙发展史
  • sql实战解析-sum()over(partition by xx order by xx)
  • ui文件转py程序的工具
  • Elasticsearch(ES)基础查询语法的使用
  • 【生产力工具】ChatGPT for Windows桌面版本安装教程
  • python milvus及curl命令进行query请求
  • HarmonyOS NEXT:华为分享-碰一碰开发分享
  • Linux内核源码目录结构
  • Linux:文件描述符fd、系统调用open
  • 【Unity3D】3D物体摆放、场景优化案例Demo
  • AI 在制造行业的探究
  • 使用 OpenCV 和 Python 轻松实现人脸检测
  • C语言程序设计十大排序—选择排序
  • [unity 高阶]使用ASE制作一个cubed的skybox的shader,跟做版本
  • ChatGPT开发教程指南
  • HTML 元素详解:从入门到精通
  • 数据结构 链表2
  • 深度学习python基础(第二节) 分支语句和循环语句
  • 国家安全部发布《网络安全法》解读
  • 基于单片机的智能台灯设计
  • Spring 6 第6章——单元测试:Junit
  • golang基于gin框架的脚手架开发
  • SpringBoot连接多数据源MySQL、SqlServer等(MyBatisPlus测试)
  • 医学图像分析工具09.1:Brainstorm安装教程
  • 【高阶数据结构】布隆过滤器(BloomFilter)
  • 智能集群无人机组网技术关键要素详解