【问题标题】:std::ifstream read 32 bits at a timestd::ifstream 一次读取 32 位
【发布时间】: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;
}

【问题讨论】:

    标签: c++


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 太好了。我唯一的问题是它是否是任意二进制数据,即这些值可能不是有效的 UTF-32 代码点,但我仍然想一次读取 32 位。似乎可用的语言环境不支持一次“哑”读取 32 位 -> en.cppreference.com/w/cpp/locale/locale。大概 std::codecvt 会对数据进行一些检查。
    猜你喜欢
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    相关资源
    最近更新 更多