2024.12.20,数据结构课项目,解压与自解压,记录

std::ifstream有什么成员函数

std::ifstream 是 C++ 标准库中的输入文件流类,用于从文件中读取数据。它继承自 std::istream,因此具有 std::istream 的所有成员函数。此外,它还提供了一些特定于文件操作的成员函数。

常用成员函数

  1. 构造函数

    • 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):打开指定文件。
  2. 打开和关闭文件

    • 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():关闭文件。
  3. 检查文件状态

    • bool is_open() const:检查文件是否成功打开。
    • bool good() const:检查流是否处于良好状态。
    • bool eof() const:检查是否到达文件末尾。
    • bool fail() const:检查流是否处于错误状态。
    • bool bad() const:检查流是否处于不可恢复的错误状态。
  4. 读取数据

    • 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 或文件末尾。
  5. 文件位置操作

    • std::ifstream& seekg(std::streampos pos):设置输入位置指针到指定位置 pos
    • std::ifstream& seekg(std::streamoff off, std::ios::seekdir dir):设置输入位置指针到相对于 dir 的偏移量 off
    • std::streampos tellg():返回输入位置指针的当前位置。
  6. 其他成员函数

    • 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;
}

解释

  1. 包含头文件#include <fstream> 用于文件流操作,#include <vector> 用于动态数组。
  2. 打开文件std::ifstream inFile(fileName, std::ios::binary); 以二进制模式打开文件。
  3. 检查文件是否成功打开if (!inFile) 检查文件是否成功打开。
  4. 获取文件大小
    • inFile.seekg(0, std::ios::end); 将文件指针移动到文件末尾。
    • std::streamsize fileSize = inFile.tellg(); 获取文件大小。
    • inFile.seekg(0, std::ios::beg); 将文件指针移动回文件开头。
  5. 读取文件内容到缓冲区
    • std::vector<char> buffer(fileSize); 创建一个缓冲区,大小为文件大小。
    • inFile.read(buffer.data(), fileSize); 将文件内容读取到缓冲区。
  6. 关闭文件inFile.close(); 关闭文件。

通过这种方式,可以将二进制文件的内容读取到缓冲区中进行处理。

seekg()是什么

seekg() 是 C++ 标准库中的一个成员函数,用于设置输入文件流(std::ifstreamstd::istream)的读取位置。它有两个重载版本:

  1. seekg(std::streampos pos):将文件读取位置设置为绝对位置 pos
  2. 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;
}

解释

  1. 打开文件std::ifstream inFile("example.bin", std::ios::binary); 以二进制模式打开文件。
  2. 移动文件指针到文件末尾inFile.seekg(0, std::ios::end); 将文件指针移动到文件末尾。
  3. 获取文件大小std::streampos fileSize = inFile.tellg(); 获取文件指针当前位置(即文件大小)。
  4. 移动文件指针回文件开头inFile.seekg(0, std::ios::beg); 将文件指针移动回文件开头。
  5. 读取文件内容inFile.read(buffer.data(), fileSize); 将文件内容读取到缓冲区。
  6. 关闭文件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;
}

解释

  1. 包含头文件#include <fstream> 用于文件流操作,#include <vector> 用于动态数组。
  2. 打开文件std::ifstream inFile(fileName, std::ios::binary); 以二进制模式打开文件。
  3. 检查文件是否成功打开if (!inFile) 检查文件是否成功打开。
  4. 获取文件大小

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();
}

解释

  1. 获取文件大小

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 对象有足够的空间来存储读取的数据,从而避免内存访问错误。

posted @ 2024-12-21 13:11  Kazuma_124  阅读(1)  评论(0编辑  收藏  举报