如何从 std::ifstream 将文件读入 unsigned char 数组?

问题描述 投票:0回答:1

所以通常我会做这样的事情:

    std::ifstream stream;
    int buff_length = 8192;
    boost::shared_array<char> buffer( new char[buff_length]);
    stream.open( path.string().c_str(), std::ios_base::binary);
    while (stream)
    {
            stream.read(buffer.get(), buff_length);
            //boost::asio::write(*socket, boost::asio::buffer(buffer.get(), stream.gcount()));
    }
    stream.close();

我想知道如何读入

unsigned char
缓冲区(
boost::shared_array<unsigned char> buffer( new unsigned char[buff_length]);

c++ boost std boost-iostreams
1个回答
15
投票

最简单的形式:

std::vector<unsigned char> vec(
      std::istreambuf_iterator<char>(std::cin)
    , std::istreambuf_iterator<char>()
    );

std::cin
替换为您的实际流。

上面的代码可能会执行多次内存分配(对于大于几个字节的文件),因为

std::istreambuf_iterator<>
是一个输入迭代器,而不是随机访问或前向迭代器,因此文件的长度可以' t 通过减去
end - begin
等迭代器或调用
std::distance(begin, end)
来测量。如果首先创建空向量,则可以减少到一次内存分配,然后调用
std::vector<>::reserve()
为文件长度分配内存,最后调用范围插入
vec.insert(vec.end(), beg, end)
,其中
beg
end
std::istreambuf_iterator<>
如上所述读取整个文件。

C++17 标准库可以做到这一点:

#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>

std::vector<unsigned char> load_file(std::filesystem::path file_path) {
    using namespace std;

    // Allocate memory for the entire file once.
    vector<unsigned char> file_content;
    file_content.reserve(file_size(file_path)); // C++17 standard library provides file_size.

    // Open the file in binary mode and read its bytes into the vector.
    ifstream file_stream(file_path, ios_base::in | ios_base::binary);
    file_content.insert(file_content.end(), istreambuf_iterator<char>{file_stream}, {});

    return file_content;
}

int main() {
    // Load a file.
    auto file_content = load_file("/usr/share/doc/gcc/copyright");

    // Output file contents into std::cout.
    copy(file_content.begin(), file_content.end(), std::ostreambuf_iterator<char>{std::cout});
}

如果文件大小超过几千字节,则将其映射到进程内存中可能是最有效的,以避免将内存从内核复制到用户空间。

使用

std::istreambuf_iterator<char>
的原因是因为实现使用
std::char_traits<>
,通常仅专门针对
char
wchar_t
。无论如何,C 和 C++ 标准要求所有
char
类型具有相同的二进制布局,没有填充位,因此
char
unsigned char
signed char
之间的转换(它们都是不同的类型,与
signed int
int
是同一类型)保留位模式,因此是安全的。

[基本.根本/1]

普通

char
signed char
unsigned char
是三种不同的类型,统称为 窄字符类型。一个
char
、一个
signed char
、一个
unsigned char
占用相同的存储空间,并且具有相同的对齐要求;也就是说,它们具有相同的对象表示...对于窄字符类型,对象表示的所有位都参与值表示...对于无符号窄字符类型,值表示的每个可能的位模式代表一个不同的数字。这些要求不适用于其他类型。在任何特定的实现中,普通
char
对象可以采用与
signed char
unsigned char
相同的值;哪一个是实现定义的。对于 0 到 255(含)范围内的每个
i
类型的值
unsigned char
,都存在一个
j
类型的值
char
,使得从
i
char
的积分转换结果为
j 
,从
j
unsigned char
积分转换的结果是
i

© www.soinside.com 2019 - 2024. All rights reserved.