【问题标题】:How do I set the number of bytes read by ifstream get()?如何设置 ifstream get() 读取的字节数?
【发布时间】:2021-08-26 02:26:58
【问题描述】:

我正在尝试解析 MIDI,它需要一次读取 8 位(一个字节)。在我的系统 (*) 上,ifs.get() 似乎一次抓取 32 位。

std::ifstream ifs;
ifs.open(FileName, std::fstream::in | std::ios::binary);

std::cout << "size:: " << sizeof(ifs.get()) <<std::endl; // returns 4

是否可以简单地指定每次读取的字节数,以便 ifs.get() 一次只能获取一个字节(8 位)?

我相信ifs.get()返回超过8位的原因是:

uint16_t nReadByte = 0;
nReadByte = ifs.get();
std::cout << std::hex << nReadByte <<std::endl;

产生如下结果:

3e,28,0,42,28,0,3b,28

但如果我将变量大小设置为 8 位,我会得到奇怪的字符:

uint8_t nReadByte = 0;
nReadByte = ifs.get();            
std::cout << std::hex << nReadByte <<std::endl;

@,,,,.,4,p,s,2,。 (这些似乎在这里没有正确呈现,但有时它们看起来像单个字形中的字母 ETXCAN

【问题讨论】:

  • 您错误地使用了sizeof
  • 确定ifs.get()返回多少字节的正确方法是什么?

标签: c++ ifstream


【解决方案1】:

在我的系统 (*) 上,ifs.get() 似乎一次抓取 32 位。

你的例子证明这是不正确的。首先,sizeof 中的 ifs.get() 甚至不会被评估,因为 sizeof 中的表达式不会被评估。其次,std::ifstreamstd::basic_ifstream&lt;char&gt; 的别名,ifs.get() 不带参数确实会返回std::basic_ifstream 的字符类型的一个字符。由于在您的情况下这是char,如果CHAR_BIT(在&lt;climits&gt; 中定义)在您的系统上定义为8,那么它确实会一次读取8 位。

sizeof(ifs.get()) 是 4 的原因是因为ifs.get() 的返回值是std::ifstream::traits_type::int_typeint(返回值不是char 的原因是因为它可能需要返回std::ifstream::traits_type::eof() 为这可能不适合char)。在您的系统上,sizeof (int) 是 4。

uint16_tuint8_t 的输出看起来不同的原因似乎是 uint16_t 它实际上将字节打印为十六进制,而对于 uint8_t 它似乎打印为字符(uint8_t 是别名unsigned charostreams 重载 operator&lt;&lt;(unsigned char) 以打印字符),这就是为什么有些没有显示并且输出通常看起来不同的原因。

【讨论】:

    【解决方案2】:

    如何设置ifstream get()读取的字节数?

    第二个参数是要读取的字节数,如果你给一个缓冲区作为第一个参数。

    在我的系统 (*) 上,ifs.get() 似乎一次抓取 32 位。

    你错了。 nullary 重载恰好读取一个字节。返回类型是int,因此除了char 的所有可能值之外,它还可以表示EOF(文件结尾),它是char 范围之外的特殊值,如果流已到达则返回结束。

    uint16_t nReadByte = 0;
    nReadByte = ifs.get();
    std::cout << std::hex << nReadByte <<std::endl;
    

    uint16_t unsigned shortunsigned int 的别名,它们都不是字符类型。当你在字符流中插入一个非字符整数时,它会被表示为一个与其数值对应的数字;在这种情况下由std::hex 操纵器修改。

    但如果我将变量大小设置为 8 位,我会得到奇怪的字符:

    uint8_t nReadByte = 0;
    nReadByte = ifs.get();            
    std::cout << std::hex << nReadByte <<std::endl;
    

    uint8_t unsigned char 的别名,它是一种字符类型。将字符插入字符流时,不会用与其数值对应的数字来表示。相反,它将由与当前字符编码中的值对应的符号表示。有些值不是可见的符号,而是影响终端行为的控制字符。

    如果要流式传输字符对象的数值,则必须转换为另一种整数类型,例如unsigned int

    (这些似乎没有正确呈现在这里

    当在没有意义的上下文中使用时,控制字符可能会以可见的符号显示很有帮助,但并非所有字体都有这样的占位符,网站在处理用户输入时通常会删除它们。

    【讨论】:

      【解决方案3】:

      似乎 ifstream::read 更好。

      来自https://www.cplusplus.com/reference/istream/istream/read/

      istream& read (char* s, streamsize n);
      

      读取数据块

      从流中提取 n 个字符,并将它们存储在 s 指向的数组中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-28
        • 1970-01-01
        相关资源
        最近更新 更多