2024.12.20,数据结构课项目,解压与自解压,记录
std::ifstream有什么成员函数
std::ifstream
是 C++ 标准库中的输入文件流类,用于从文件中读取数据。它继承自 std::istream
,因此具有 std::istream
的所有成员函数。此外,它还提供了一些特定于文件操作的成员函数。
常用成员函数
-
构造函数:
std::ifstream()
:默认构造函数。std::ifstream(const char* filename, std::ios::openmode mode = std::ios::in)
:打开指定文件。std::ifstream(const std::string& filename, std::ios::openmode mode = std::ios::in)
:打开指定文件。
-
打开和关闭文件:
void open(const char* filename, std::ios::openmode mode = std::ios::in)
:打开指定文件。void open(const std::string& filename, std::ios::openmode mode = std::ios::in)
:打开指定文件。void close()
:关闭文件。
-
检查文件状态:
bool is_open() const
:检查文件是否成功打开。bool good() const
:检查流是否处于良好状态。bool eof() const
:检查是否到达文件末尾。bool fail() const
:检查流是否处于错误状态。bool bad() const
:检查流是否处于不可恢复的错误状态。
-
读取数据:
std::ifstream& read(char* s, std::streamsize n)
:从文件中读取n
个字符到缓冲区s
。std::ifstream& getline(char* s, std::streamsize n)
:从文件中读取一行到缓冲区s
,最多读取n-1
个字符。std::ifstream& getline(char* s, std::streamsize n, char delim)
:从文件中读取一行到缓冲区s
,最多读取n-1
个字符,直到遇到分隔符delim
。std::ifstream& get(char& c)
:从文件中读取一个字符到c
。std::ifstream& get(char* s, std::streamsize n)
:从文件中读取n-1
个字符到缓冲区s
,直到遇到换行符或文件末尾。std::ifstream& get(char* s, std::streamsize n, char delim)
:从文件中读取n-1
个字符到缓冲区s
,直到遇到分隔符delim
或文件末尾。
-
文件位置操作:
std::ifstream& seekg(std::streampos pos)
:设置输入位置指针到指定位置pos
。std::ifstream& seekg(std::streamoff off, std::ios::seekdir dir)
:设置输入位置指针到相对于dir
的偏移量off
。std::streampos tellg()
:返回输入位置指针的当前位置。
-
其他成员函数:
void clear()
:清除流的错误状态。void clear(std::ios::iostate state)
:设置流的错误状态为state
。
示例代码
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream inFile("example.txt", std::ios::binary);
if (!inFile.is_open()) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
// 读取文件内容
std::string content((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());
std::cout << "文件内容:" << std::endl << content << std::endl;
// 关闭文件
inFile.close();
return 0;
}
通过这些成员函数,可以方便地进行文件的打开、关闭、读取和状态检查等操作。
如何读取二进制格式的数据
读取二进制格式的数据可以使用 std::ifstream
以二进制模式打开文件,并使用 read
方法将数据读取到缓冲区。以下是一个示例,展示如何读取二进制文件并将其内容存储到缓冲区中:
示例代码
读取二进制文件
#include <iostream>
#include <fstream>
#include <vector>
std::vector<char> readBinaryFile(const std::string& fileName) {
std::ifstream inFile(fileName, std::ios::binary);
if (!inFile) {
std::cerr << "无法打开文件" << std::endl;
return {};
}
// 获取文件大小
inFile.seekg(0, std::ios::end);
std::streamsize fileSize = inFile.tellg();
inFile.seekg(0, std::ios::beg);
// 读取文件内容到缓冲区
std::vector<char> buffer(fileSize);
if (!inFile.read(buffer.data(), fileSize)) {
std::cerr << "读取文件失败" << std::endl;
return {};
}
inFile.close();
return buffer;
}
int main() {
std::string fileName = "example.bin";
std::vector<char> fileContent = readBinaryFile(fileName);
if (!fileContent.empty()) {
std::cout << "文件内容读取成功,大小:" << fileContent.size() << " 字节" << std::endl;
}
return 0;
}
解释
- 包含头文件:
#include <fstream>
用于文件流操作,#include <vector>
用于动态数组。 - 打开文件:
std::ifstream inFile(fileName, std::ios::binary);
以二进制模式打开文件。 - 检查文件是否成功打开:
if (!inFile)
检查文件是否成功打开。 - 获取文件大小:
inFile.seekg(0, std::ios::end);
将文件指针移动到文件末尾。std::streamsize fileSize = inFile.tellg();
获取文件大小。inFile.seekg(0, std::ios::beg);
将文件指针移动回文件开头。
- 读取文件内容到缓冲区:
std::vector<char> buffer(fileSize);
创建一个缓冲区,大小为文件大小。inFile.read(buffer.data(), fileSize);
将文件内容读取到缓冲区。
- 关闭文件:
inFile.close();
关闭文件。
通过这种方式,可以将二进制文件的内容读取到缓冲区中进行处理。
seekg()是什么
seekg()
是 C++ 标准库中的一个成员函数,用于设置输入文件流(std::ifstream
或 std::istream
)的读取位置。它有两个重载版本:
seekg(std::streampos pos)
:将文件读取位置设置为绝对位置pos
。seekg(std::streamoff off, std::ios::seekdir dir)
:将文件读取位置设置为相对于dir
的偏移量off
。
参数说明
pos
:一个绝对位置,通常由tellg()
返回。off
:一个相对偏移量。dir
:一个方向,可以是以下值之一:std::ios::beg
:文件开头。std::ios::cur
:当前位置。std::ios::end
:文件末尾。
示例代码
以下示例展示了如何使用 seekg()
设置文件读取位置:
#include <iostream>
#include <fstream>
int main() {
std::ifstream inFile("example.bin", std::ios::binary);
if (!inFile) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
// 将文件指针移动到文件末尾
inFile.seekg(0, std::ios::end);
std::streampos fileSize = inFile.tellg(); // 获取文件大小
std::cout << "文件大小: " << fileSize << " 字节" << std::endl;
// 将文件指针移动回文件开头
inFile.seekg(0, std::ios::beg);
// 读取文件内容
std::vector<char> buffer(fileSize);
inFile.read(buffer.data(), fileSize);
// 关闭文件
inFile.close();
return 0;
}
解释
- 打开文件:
std::ifstream inFile("example.bin", std::ios::binary);
以二进制模式打开文件。 - 移动文件指针到文件末尾:
inFile.seekg(0, std::ios::end);
将文件指针移动到文件末尾。 - 获取文件大小:
std::streampos fileSize = inFile.tellg();
获取文件指针当前位置(即文件大小)。 - 移动文件指针回文件开头:
inFile.seekg(0, std::ios::beg);
将文件指针移动回文件开头。 - 读取文件内容:
inFile.read(buffer.data(), fileSize);
将文件内容读取到缓冲区。 - 关闭文件:
inFile.close();
关闭文件。
通过 seekg()
,可以灵活地设置文件读取位置,从而实现对文件的随机访问。
vector的.data()是什么
std::vector::data()
是 C++ 标准库中的一个成员函数,用于返回指向
vector
内部数组的指针。这个指针可以用于访问或操作
vector
中的元素,就像操作普通数组一样。
语法
T* data() noexcept;
const T* data() const noexcept;
返回值
- 返回指向
vector
内部数组的指针。如果
vector
为空,则返回的指针是一个有效的指针,但解引用它是未定义行为。
示例代码
以下示例展示了如何使用 std::vector::data()
读取文件内容到
vector
中,并通过
data()
访问内部数组:
#include <iostream>
#include <fstream>
#include <vector>
int main() {
std::string fileName = "example.bin";
std::ifstream inFile(fileName, std::ios::binary);
if (!inFile) {
std::cerr << "无法打开文件" << std::endl;
return 1;
}
// 获取文件大小
inFile.seekg(0, std::ios::end);
std::streamsize fileSize = inFile.tellg();
inFile.seekg(0, std::ios::beg);
// 读取文件内容到 vector
std::vector<char> fileContent(fileSize);
if (!inFile.read(fileContent.data(), fileSize)) {
std::cerr << "读取文件失败" << std::endl;
return 1;
}
inFile.close();
// 通过 data() 访问 vector 内部数组
char* data = fileContent.data();
for (std::streamsize i = 0; i < fileSize; ++i) {
std::cout << data[i];
}
return 0;
}
解释
- 包含头文件:
#include <fstream>
用于文件流操作,#include <vector>
用于动态数组。 - 打开文件:
std::ifstream inFile(fileName, std::ios::binary);
以二进制模式打开文件。 - 检查文件是否成功打开:
if (!inFile)
检查文件是否成功打开。 -
获取文件大小:
inFile.seekg(0, std::ios::end);
将文件指针移动到文件末尾。
std::streamsize fileSize = inFile.tellg();
获取文件大小。
inFile.seekg(0, std::ios::beg);
将文件指针移动回文件开头。
5. **读取文件内容到
vector
**:
std::vector<char> fileContent(fileSize);
创建一个缓冲区,大小为文件大小。
inFile.read(fileContent.data(), fileSize);
将文件内容读取到缓冲区。
6. **通过
data()
访问
vector
内部数组**:
char* data = fileContent.data();
获取指向
vector
内部数组的指针。
- 遍历并输出数组内容。
通过 std::vector::data()
,可以方便地访问
vector
内部的数组,从而与需要指针的函数或库进行交互。
inFile.read((char*)&data, fileSize)为什么失败
inFile.read((char*)&data, fileSize)
失败的原因是因为
data
是一个 std::string
对象,而不是一个字符数组。std::ifstream::read
需要一个指向字符数组的指针,而不是一个指向 std::string
对象的指针。
要正确地将文件内容读取到 std::string
对象中,可以使用 std::string
的
data()
方法来获取指向内部字符数组的指针。以下是修正后的代码:
修正后的代码
readOriginalFile
方法
void HuffmanTree::readOriginalFile(std::string fileName) {
std::ifstream inFile(fileName, std::ios::binary);
if (!inFile) {
std::cerr << "文件打开失败" << std::endl;
exit(1);
}
// 获取文件大小
inFile.seekg(0, std::ios::end); // 将文件读取位置设置为文件末尾
std::streamsize fileSize = inFile.tellg();
inFile.seekg(0, std::ios::beg); // 将读取位置设置为文件开头
// 提前设定 std::string 对象的长度
data = std::string(fileSize, '\0');
// 读取文件内容到 std::string 对象
if (!inFile.read(&data[0], fileSize)) {
std::cerr << "文件读取失败" << std::endl;
exit(1);
}
buildTree(data);
encode(data, encodedData);
inFile.close();
}
解释
-
获取文件大小:
inFile.seekg(0, std::ios::end);
将文件指针移动到文件末尾。
std::streamsize fileSize = inFile.tellg();
获取文件大小。
inFile.seekg(0, std::ios::beg);
将文件指针移动回文件开头。
2. 提前设定 std::string
对象的长度:
data = std::string(fileSize, '\0');
创建一个字符串,大小为文件大小,并初始化为 '\0'
。
3. 读取文件内容到 std::string
对象:
inFile.read(&data[0], fileSize);
使用 std::string
的
data()
方法来获取指向内部字符数组的指针,并将文件内容读取到字符串。
通过这种方式,可以确保 std::string
对象有足够的空间来存储读取的数据,从而避免内存访问错误。