无法使用 fstream 从二进制文件中读取字符串,而是显示奇怪的符号

Posted

技术标签:

【中文标题】无法使用 fstream 从二进制文件中读取字符串,而是显示奇怪的符号【英文标题】:Cannot read a string from a binary file using fstream, it is showing weird symbols instead 【发布时间】:2019-03-28 04:21:30 【问题描述】:

我正在尝试读取我制作的 .bin 文件,该文件在结构中包含两个整数和一个字符串。 int 显示正常,但字符串输出显示奇怪的符号。

这是写脚本:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct student
    int no;
    string name;
    int score;
;

int main()
    fstream myFile;
    myFile.open("data.bin", ios::trunc | ios::out | ios::in | ios::binary);

    student jay, brad;

    jay.no = 100;
    jay.name = "Jay";
    jay.score = 95;

    brad.no = 200;
    brad.name = "Brad";
    brad.score = 83;

    myFile.write(reinterpret_cast<char*>(&jay),sizeof(student));
    myFile.write(reinterpret_cast<char*>(&brad),sizeof(student));

    myFile.close();

    cin.get();
    return 0;

这是读取脚本:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct student
    int no;
    string name;
    int score;
;

int main()
    fstream myFile;
    myFile.open("data.bin", ios::in | ios::binary);

    student readFile;

    myFile.seekp(1*sizeOf(student)); //I use this because I want only specific position 
                                     //to be shown, for example I put 1 to show only Brad

    myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
    cout << "No   : " << readFile.no << endl;
    cout << "Name : " << readFile.name << endl;
    cout << "Score: " << readFile.score << endl;

    myFile.close();

    cin.get();
    return 0;

结果会是这样的:

No   : 200
Name : ñ∩K 
Score: 83

字符串显示“ñ∩K”而不是“Brad”。 我尝试不使用seekp,并使用两次读取:

    myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
    cout << "No   : " << readFile.no << endl;
    cout << "Name : " << readFile.name << endl;
    cout << "Score: " << readFile.score << endl;

    myFile.read(reinterpret_cast<char*>(&readFile),sizeof(student));
    cout << "No   : " << readFile.no << endl;
    cout << "Name : " << readFile.name << endl;
    cout << "Score: " << readFile.score << endl;

结果是:

No   : 100
Name : Jay
Score: 95

No   : 200
Name : ε@ 
Score: 83

如您所见,第一个位置显示“Jay”很好,但下一个位置不是。知道出了什么问题吗?我是 C++ 新手。

【问题讨论】:

你不能writestd::stringstring 对于简单的二进制转储来说结构过于复杂。您将不得不(传入的搜索词!)序列化。 string 的二进制存储包含大小信息、指向 sring 内容所在堆的 ptr 等。有一种叫做小字符串优化的东西可以消除堆存储并将小字符串放在同一个块中。不要将字符串保存为二进制对象,因为您无法读取它们。 理论上有可能,根据 C++ 标准库,由于所谓的小字符串优化,特别短的字符串(大约 16 到 23 个字符)可以这样编写,但你绝对应该不要指望那个。 您可能会发现这个问题很有帮助:***.com/questions/7046244/… 【参考方案1】:

您写入文件的不是字符串,而是std::string 对象的内部结构。很可能这是一个指针。当您重新读取它时,指针将指向无效的东西。你很幸运能得到任何输出,而不是崩溃,或者恶魔从你的鼻孔飞出。

【讨论】:

供参考:nasal demons 是 undefined behavior 的行话。意思是程序做非法的事情(比如读取随机内存)可能会产生任何奇怪的和无法预料的效果。

以上是关于无法使用 fstream 从二进制文件中读取字符串,而是显示奇怪的符号的主要内容,如果未能解决你的问题,请参考以下文章

从二进制文件中读取矩阵

使用 fstream 的替代方案

尝试从二进制文件读取时引发违规

PHP如何将从二进制文件中读取的字节转换为数字

C ++从文件流中读取无符号字符

在python中如何从二进制文件中读取信息