【c++】文件操作

在C++语言中,有四个已预先定义好的流对象
std::cin:用于处理标准输入。
std::cout:用于处理标准输出。
std::cerr:用于处理标准出错信息,并提供不带缓中区的输出。
std::clog:也用于处理标准出错信息,但提供带有缓冲区的输出。
C++中常见的文件操作模式
在C++中,常见的文件操作模式有以下几种:
输入模式( std::ios::in):用于读取文件内容。(读取文件的内容可以使用这个std::ifstream)
输出模式( std::ios::out):用于写入文件内容。如果文件已存在,则会先清空原有内容再写入新内容。(向文件中写入内容可以使用这个std::ofstream)
附加模式( std::ios::app):用于在文件末尾追加内容。如果文件不存在,则会创建新文件
二进制模式( std::ios::binary):以二进制格式进行读写操作,适用于处理非文本数据。
截断模式( std::ios::trunc):在打开文件时,如果文件已经存在,则清空其内容。

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

int main()
{
	//写文件
	std::ofstream oFile("test.txt");
	if (!oFile.is_open())
	{
		std::cout << "open file error!" << std::endl;
	}
	oFile << "hello world!" << std::endl << "hello world!";
	oFile << "hello world!" << std::endl;
	oFile.close();

	//覆盖文件的内容
	std::ofstream oFile1("test.txt");
	if (!oFile1.is_open())
	{
		std::cout << "open file error!" << std::endl;
	}
	oFile1 << "您好!" << std::endl;
	oFile1.close();

	//追加文件内容
	std::ofstream oFile2("test.txt", std::ios::app);
	if (!oFile2.is_open())
	{
		std::cout << "open file error!" << std::endl;
	}
	oFile2 << "append" << std::endl;
	oFile2.close();

	//读文件内容
	std::ifstream iFile("test.txt");
	if (!iFile.is_open())
	{
		std::cout << "open file error!" << std::endl;
	}
	std::string line;
	while (getline(iFile, line))
	{
		std::cout << line << std::endl;
	}
	iFile.close();

	system("pause");
}

在这里插入图片描述
如果需要同时读写文件,可以使用std::fstream:

#include <fstream>
std::fstream ioFile("test.txt", std::ios::in | std::ios::out);

C++如何将当前位置移动到文件任意位置
在C++中,将文件流的位置指针移动到文件的任意位置可以通过std::fstream、std::ifstream或std::ofstream中的成员函数seekg()和seekp()来实现。这两个函数分别用于读取和写入操作的位置移动。对于读取操作,使用seekg();对于写入操作,使用seekp()

这些函数接受两个参数:第一个是偏移量,第二个是参考点。参考点可以是以下预定义的枚举值之一:
std::ios_base::beg:文件的开始位置
std::ios_base::cur:文件的当前位置
std::ios_base::end:文件的结束位置

注意:std::ios::binary 模式对于文件指针的精确控制是非常重要的,特别是在您想要使用 seekg 函数进行相对或绝对的文件位置移动时。在文本模式下(即没有指定 std::ios::binary),std::ifstream 会对输入进行特殊处理,比如转换换行符(在Windows系统上,可能会将 \n 转换为 \r\n 或将 \r\n 转换为 \n)。这种转换可能导致文件指针的位置与您期望的位置不匹配,因为每次读取或写入字符时,文件指针可能会移动多个字节(而不是一个字节)。

因此,如果您想要确保 seekg 函数按照您指定的字节偏移量精确地移动文件指针,那么您应该使用 std::ios::binary 模式打开文件。

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

int main()
{
	//写文件
	std::ofstream oFile("test.txt");
	if (!oFile.is_open())
	{
		std::cout << "open file error!" << std::endl;
	}
	oFile << "hello world!" << std::endl;
	oFile.close();

	std::ifstream file("test.txt", std::ios::binary);

	if (file.is_open()) {
		// 移动读取位置到文件的第10个字节
		if (file.seekg(10, std::ios::beg).fail()) {
			std::cerr << "移动到文件中的位置10时出错。" << std::endl;
			return 1;
		}

		// 注意:如果文件大小小于10个字节,下面的操作将会失败
		// 或者从当前位置向前移动5个字节(只有当当前位置大于或等于5时才有意义)
		// 这里假设我们之前已经成功移动到了文件的第10个字节
		if (file.tellg() >= 5) // 使用tellg()检查当前位置
		{ 
			if (file.seekg(-5, std::ios::cur).fail()) {
				std::cerr << "从当前位置向前移动5个字节时出错。" << std::endl;
				return 1;
			}
		}
		else {
			std::cerr << "无法从当前位置向前移动5个字节,因为它离开头太近了。" << std::endl;
			// 处理错误或继续执行其他操作
		}

		// 移动到文件末尾前10个字节
		if (file.seekg(-10, std::ios::end).fail()) {
			std::cerr << "移动到文件末尾前10个字节的位置时出错。" << std::endl;
			return 1;
		}

		// 现在可以从新的位置读取数据
		char buffer[256];
		file.read(buffer, sizeof(buffer) - 1); // 减1以保留空间给字符串的null终止符
		buffer[file.gcount()] = '\0'; // 设置null终止符

		// 输出读取的数据
		std::cout << "Read data: " << buffer << std::endl;
		// 关闭文件
		file.close();
	}
	system("pause");
}

在这里插入图片描述
char buffer[256];
file.read(buffer, sizeof(buffer) - 1); // 减1以保留空间给字符串的null终止符
buffer[file.gcount()] = ‘\0’; // 设置null终止符 //要加上这个,不然后面的都是乱码。

#include <fstream>
#include <iostream>

int main() {
	std::ofstream file("test.txt", std::ios::binary | std::ios::trunc);

	if (!file) {
		std::cerr << "Unable to open file." << std::endl;
		return 1;
	}

	// 移动写入位置到文件的第10个字节
	file.seekp(10, std::ios::beg);

	// 写入一些数据
	const char* data = "Hello, World!";
	file.write(data, 13);

	// 关闭文件
	file.close();
	system("pause");
	return 0;
}

C++如何判断是否已经到达文件末尾
使用eof()成员函数
大多数流类(如std::ifstream, std::ofstream, 和std::fstream)都提供了eof()成员函数,它在流达到文件末尾时返回true。但是需要注意的是,eof()通常在尝试读取操作之后才会返回true,也就是说,只有在读取操作尝试从文件末尾读取数据时,eof()才会变为true。

std::ifstream file("test.txt");
if (file.is_open()) {
    // 尝试读取数据
    char ch;
    while (file >> ch) {
        // 处理数据...
    }
    if (file.eof()) {
        std::cout << "End of file reached." << std::endl;
    }
    file.close();
}

使用peek()成员函数
另一种方法是使用peek()成员函数,它返回下一个将被读取的字符,或者如果文件已经到了末尾,则返回traits_type::eof()。你可以通过比较返回值与**traits_type::eof()**来判断是否到达文件末尾。

std::ifstream file("test.txt");
if (file.is_open()) {
    while (file.peek() != std::ifstream::traits_type::eof()) {
        // 进行读取操作...
    }
    file.close();
}

在C++中,当以二进制模式打开文件时,使用std::ifstream或std::fstream的eof()成员函数来判断是否到达文件末尾并不总是可靠的。这是因为eof()的特性是在读取操作之后返回true,仅当读取操作尝试从文件的末尾读取数据时才如此。然而,对于二进制文件,由于文件中可能包含值恰好等于EOF(通常定义为-1)的字节,这可能会导致误判。
在这种情况下,可以使用peek()函数来进行更精确的判断。
参考来源

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值