MST
星途 面试题库

面试题:C++自定义文件流类及其与标准IO库的融合

设计一个自定义的文件流类,该类能够继承自标准的C++ IO流类,实现特定的数据加密和解密功能,在读写文件时自动对数据进行加解密处理。并说明如何确保该自定义流类与标准IO库的其他组件(如iostream、sstream等)协同工作,给出完整的代码实现和详细的设计思路。
39.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 继承标准C++ IO流类:选择合适的基类,如std::basic_filebuf<char>来处理文件的读写缓冲,从它派生出自定义的文件流缓冲类。再基于这个缓冲类派生出文件流类,如std::basic_ifstream<char>std::basic_ofstream<char>的自定义版本。
  2. 数据加密和解密功能:定义加密和解密的函数。在文件读取时调用解密函数,在文件写入时调用加密函数。加密和解密算法可以根据具体需求选择,这里以简单的异或加密为例。
  3. 与标准IO库协同工作:通过继承标准的IO流类,自定义的流类自然可以与标准IO库的其他组件协同工作。例如,在需要使用文件流的地方,可以直接使用自定义的文件流类对象,就像使用标准文件流一样。

代码实现

#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>

// 简单的异或加密函数
void xorEncryptDecrypt(char* data, size_t length, char key) {
    for (size_t i = 0; i < length; ++i) {
        data[i] ^= key;
    }
}

// 自定义文件流缓冲类
class EncryptedFileBuf : public std::basic_filebuf<char> {
protected:
    char encryptionKey;
    std::streampos fileSize;

    std::streampos getFileSize() {
        std::ifstream file(this->filename(), std::ios::binary);
        file.seekg(0, std::ios::end);
        std::streampos size = file.tellg();
        file.close();
        return size;
    }

    int_type readFromDevice() override {
        if (this->gptr() >= this->egptr()) {
            std::streamsize toRead = std::min< std::streamsize >(this->bufferSize, fileSize - (this->gptr() - this->eback()));
            if (toRead <= 0) return traits_type::eof();
            std::streamsize readCount = this->underlying_filebuf()->sgetn(this->buffer, toRead);
            if (readCount <= 0) return traits_type::eof();
            xorEncryptDecrypt(this->buffer, readCount, encryptionKey);
            this->setg(this->buffer, this->buffer, this->buffer + readCount);
        }
        return traits_type::to_int_type(*(this->gptr()++));
    }

    int_type writeToDevice(char_type c) override {
        if (this->pptr() >= this->epptr()) {
            std::streamsize toWrite = this->pptr() - this->pbase();
            if (toWrite > 0) {
                xorEncryptDecrypt(const_cast<char*>(this->pbase()), toWrite, encryptionKey);
                std::streamsize writtenCount = this->underlying_filebuf()->sputn(this->pbase(), toWrite);
                if (writtenCount < toWrite) return traits_type::eof();
            }
            this->setp(this->buffer, this->buffer + this->bufferSize - 1);
        }
        *(this->pptr()++) = c;
        return traits_type::not_eof(c);
    }

    int sync() override {
        std::streamsize toWrite = this->pptr() - this->pbase();
        if (toWrite > 0) {
            xorEncryptDecrypt(const_cast<char*>(this->pbase()), toWrite, encryptionKey);
            std::streamsize writtenCount = this->underlying_filebuf()->sputn(this->pbase(), toWrite);
            if (writtenCount < toWrite) return -1;
        }
        this->setp(this->buffer, this->buffer + this->bufferSize - 1);
        return this->underlying_filebuf()->pubsync();
    }

public:
    static const std::streamsize bufferSize = 4096;
    char buffer[bufferSize];

    EncryptedFileBuf(const char* filename, char key, std::ios::openmode mode)
        : encryptionKey(key) {
        this->open(filename, mode);
        fileSize = getFileSize();
    }

    ~EncryptedFileBuf() {
        this->close();
    }

    std::basic_filebuf<char>* underlying_filebuf() {
        return this->std::basic_filebuf<char>::underlying_filebuf();
    }
};

// 自定义输入文件流类
class EncryptedIfstream : public std::basic_ifstream<char> {
public:
    EncryptedIfstream(const char* filename, char key)
        : std::basic_ifstream<char>(new EncryptedFileBuf(filename, key, std::ios::in)) {}
};

// 自定义输出文件流类
class EncryptedOfstream : public std::basic_ofstream<char> {
public:
    EncryptedOfstream(const char* filename, char key)
        : std::basic_ofstream<char>(new EncryptedFileBuf(filename, key, std::ios::out)) {}
};

使用示例

int main() {
    const char* filename = "encrypted.txt";
    char key = 'a';

    // 写入加密文件
    {
        EncryptedOfstream ofs(filename, key);
        ofs << "Hello, World!";
    }

    // 读取解密文件
    {
        EncryptedIfstream ifs(filename, key);
        std::string line;
        std::getline(ifs, line);
        std::cout << line << std::endl;
    }

    return 0;
}

说明

  1. 加密和解密函数xorEncryptDecrypt函数使用简单的异或操作对数据进行加密和解密。实际应用中可替换为更安全的加密算法。
  2. 自定义文件流缓冲类EncryptedFileBuf继承自std::basic_filebuf<char>,重写了readFromDevicewriteToDevicesync等虚函数,在读写数据时调用加密和解密函数。
  3. 自定义文件流类EncryptedIfstreamEncryptedOfstream分别继承自std::basic_ifstream<char>std::basic_ofstream<char>,使用自定义的EncryptedFileBuf来实现加密和解密的文件读写。
  4. 与标准IO库协同工作:由于EncryptedIfstreamEncryptedOfstream继承自标准的文件流类,它们可以像标准文件流一样与iostreamsstream等标准IO库组件协同工作,例如在std::getline中使用自定义的输入文件流。