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
的指针会发生什么情况?
此外,*buffer
与 buffer[0]
完全相同。所以在函数内部你只打印buffer
的第一个“字符”。
为了解决前两个问题,我建议您使用std::vector<std::byte>
(或std::vector<std::uint8_t>
,如果您没有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<char>
或 std::string
来保存此类数据,因为它们将保存有关大小的信息,并自行清理。
【讨论】:
由于二进制文件中存在空字节,使用 iostream 输出缓冲区将毫无意义。最好循环输出每个字节的unsigned char
十六进制值(或至少一个值得BMP file format 的标头)以上是关于c++ fstream::read 只返回第一个字符的主要内容,如果未能解决你的问题,请参考以下文章