std::ifstream 一次读取 32 位

Posted

技术标签:

【中文标题】std::ifstream 一次读取 32 位【英文标题】:std::ifstream read 32 bits at a time 【发布时间】:2018-11-21 13:55:52 【问题描述】:

我想知道为什么,使用字符串流时,距离符合预期。迭代器一次迭代 32 位,我得到 6 个。

但是使用 char32_t 上的 ifstream 模板,我希望它一次读取 4 个字节,但似乎在 streambuf 内部它会读取一个字符,然后将其转换为 char32_t。所以距离是 24。

文件 test.txt 包含相同的“abcdef”,另存为 utf32 little endian,没有 bom。可用here

这是为什么?为什么在使用 std::istreambuf_iterator 时不能一次读取 32 位 std::basic_ifstream。如果这只是要读取一个 char 执行转换为 char32_t,那么模板参数的意义何在?如何使用 std::istreambuf_iterator 一次读取 32 位文件。

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

int main() 
    std::basic_string<char32_t> str = U"abcdef";
    std::basic_stringstream<char32_t> data str ;

    //std::basic_ifstream<char32_t> data("test.txt", std::ios::binary);

    size_t dist = std::distance(std::istreambuf_iterator<char32_t>(data), std::istreambuf_iterator<char32_t>());

    std::cout << dist << std::endl;

    return 0;

【问题讨论】:

【参考方案1】:

基本上,您的问题归结为两个问题:

字符串流和文件流有什么区别? 为什么 uint32_t 参数化文件流仍然读取单个字节?

这两者都用所谓的编码来解释,在流中由它们的codecvt(代码转换)方面表示。这个方面负责将外部字节转换为内存表示,反之亦然。默认方面只会将一个内部元素转换为一个外部字节,因此字节和字符之间是一对一的关系。为了以四个字节为单位读取文件,您需要使用 UCS4 或 UTF-32 代码转换方面 imbue() 流。

对于字符串流,您不指定外部序列,而是指定内部序列,因此不会发生代码转换。

【讨论】:

太好了。我唯一的问题是它是否是任意二进制数据,即这些值可能不是有效的 UTF-32 代码点,但我仍然想一次读取 32 位。似乎可用的语言环境不支持一次“哑”读取 32 位 -> en.cppreference.com/w/cpp/locale/locale。大概 std::codecvt 会对数据进行一些检查。

以上是关于std::ifstream 一次读取 32 位的主要内容,如果未能解决你的问题,请参考以下文章

通过 SWIG 在 python 中使用 std::ifstream、std::ofstream 的技术?

std::ifstream 构造函数只接受绝对路径?

为啥 std::istringstream 在三元 (?:) 运算符中的解析方式似乎与 std::ifstream 不同?

在 C++/CLI 中使用 std::basic_ifstream::get() 时出现 AccessViolationException,为啥?

fstream包含ofstream和ifstream的所有内容? [关闭]

64位读取注册表与32位的区别