c++ fstream::read 只返回第一个字符

Posted

技术标签:

【中文标题】c++ fstream::read 只返回第一个字符【英文标题】:c++ fstream::read only returning 1st char 【发布时间】:2020-12-08 08:58:17 【问题描述】:

前言:我是一个没有经验的编码员,所以它可能是一个明显的错误。就像所有这些代码都被盗并一起拍打一样,所以我声称没有此代码的所有权。

系统:我使用的是 Windows 10 64 位。我在 Notepad++ 中编写代码并使用 MinGW G++ 进行编译。

我正在尝试做的事情:我正在尝试将整个文件(BMP 格式)读入一个变量,并返回一个指向该变量的指针作为函数的返回值。

发生了什么:该变量仅存储文件的第一个字符。

char* raw_data(std::string filename)
//100% non-stolen
    std::ifstream is (filename, std::ifstream::binary);
    if (is) 
        // get length of file:
        is.seekg (0, is.end);
        int length = is.tellg();
        is.seekg (0, is.beg);
        std::cout << is.tellg() << "\n"; 
        
        char * buffer = new char [length];
        std::cout << "Reading " << length << " characters... \n";
        // read data as a block:
        is.read (buffer,length);
        std::cout << "\n\n" << *buffer << "\n\n";
    
        if (is)
            std::cout << "all characters read successfully.";
        else
            std::cout << "error: only " << is.gcount() << " could be read";
        is.close();
        // ...buffer contains the entire file...
//101% non-stolen
        return buffer;
    
    return ;

调用函数的代码是

char * image_data = new char [image_size];
        image_data = raw_data("Bitmap.bmp");

编译正常,EXE输出

0
Reading 2665949 characters...


B

all characters read successfully.

Bitmap.bmp 文件开始:

BM¶ƒ     6   (   €  ‰        €ƒ Δ  Δ          ¨δό¨δό¨δό¨

如您所见,变量 buffer 仅存储 Bitmap.bmp 的第一个字符(如果我更改第一个字符,它也会更改)

任何帮助将不胜感激。 感谢您的宝贵时间。

【问题讨论】:

请记住,C 风格的字符串实际上称为 null-terminated 字符串。 null-terminator 是字节0。原始二进制文件包含大量 0 字节。您不能将原始二进制数据视为字符串。 另一方面,您有内存泄漏。重新分配该变量后,最初分配给 image_data 的指针会发生什么情况? 此外,*bufferbuffer[0] 完全相同。所以在函数内部你只打印buffer的第一个“字符”。 为了解决前两个问题,我建议您使用std::vector&lt;std::byte&gt;(或std::vector&lt;std::uint8_t&gt;,如果您没有std::byte)作为数据容器。首先它不会轻易被视为“字符串”,其次它具有自动处理内存。 【参考方案1】:
std::cout << "\n\n" << *buffer << "\n\n";

缓冲区是一个char*,所以通过取消引用它你会得到一个char,在你的例子中是B。如果你想输出你读取的整个数据,不要取消引用指针,在C /C++ char* 输出时有std::cout,printf等特殊处理。

std::cout << "\n\n" << buffer << "\n\n";

请记住,按照惯例,char* 中的 C 字符串应该以 null 结尾,而您的则不是,而且您的函数的调用者没有有效的方法来检查它有多长,这些信息会像函数一样丢失strlen 期望 Cstring 也以空值结尾。您应该查看 std::vector&lt;char&gt;std::string 来保存此类数据,因为它们将保存有关大小的信息,并自行清理。

【讨论】:

由于二进制文件中存在空字节,使用 iostream 输出缓冲区将毫无意义。最好循环输出每个字节的unsigned char 十六进制值(或至少一个值得BMP file format 的标头)

以上是关于c++ fstream::read 只返回第一个字符的主要内容,如果未能解决你的问题,请参考以下文章

面试题50:第一个只出现一次的字符(C++)

c++ 获取注册表项只返回一个字符

函数返回两个字符串的第一个公共字符

Process API不返回ms字处理的所有实例

在 C++ 中打印出字节流

硬核两万字文章带你C++入门