简体   繁体   English

从文件读取时获取垃圾字符

[英]getting garbage characters while reading from file

I have a CS project and I am trying to write/read strings into a string variable, say x of size 10. I am new to coding, and I am making some mistake with writing to file. 我有一个CS项目,我试图将字符串写入/读取一个string变量,比如说x的大小为10。我是编码的新手,并且在写入文件时犯了一些错误。 Please help me. 请帮我。

Here is the class I have defined in my project file that includes my string x[10] array. 这是我在项目文件中定义的类,其中包括我的string x[10]数组。 I am pretty sure that I am making a mistake in writing to file, because it adds garbage characters in the file. 我很确定我在写入文件时犯了一个错误,因为它在文件中添加了垃圾字符。

void write_announcement()
{
    student st;          
    string line;
    int num;

    ofstream file;
    file.open("announcement.txt");

    cout << "Enter number:";
    cin >> num;

    cin.ignore();
    getline(cin,line);

    announce[num] = line;
    file.write(reinterpret_cast<char *> (&st), sizeof(student));

    file.close();
}    

void read_announcement()
{
    student st;
    int n;
    cout << "Enter n: ";
    cin >> n;

    ifstream file;
    file.open("announcement.txt");

    while (file >> st.announce[n]);
    {
       cout << announce[n];
    }

    file.close();
}

You can't write/read a std::string object as-is to/from a stream, let alone an array of strings, the way you are doing so. 您不能按原样向流中写入/读取std::string对象,更不用说按这种方式来处理字符串数组了。 You are writing/reading each string's internal data, which amongst other things consists of a pointer to character data that is stored elsewhere in memory, possibly a small buffer for short-string optimizations, etc. You are writing/reading that internal data, not the actual character data. 您正在写入/读取每个字符串的内部数据,其中包括指向存储在内存中其他位置的字符数据的指针,可能是用于短字符串优化的小缓冲区等。您正在写入/读取该内部数据,而不是实际字符数据。 That is why you are getting "garbage" in your file. 这就是为什么您的文件中出现“垃圾”的原因。

When writing, you need to serialize the string character data in a format that you can then deserialize when reading back, eg: 写入时,您需要以一种格式对字符串数据进行序列化 ,然后在回读时可以 序列化该格式,例如:

struct student
{
    string announce[10];
};

ostream& operator<<(ostream &os, const student &st)
{
    for(int x = 0; x < 10; ++x)
        os << st.announce[x] << '\n';
    return os;
}

istream& operator>>(istream &is, student &st)
{
    for(int x = 0; x < 10; ++x)
        getline(is, st.announce[x]);
    return is;
}

void write_announcement()
{
    student st;
    string line;
    int num;

    cout << "Enter number: ";
    cin >> num;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    if ((num < 0) || (num >= 10))
    {
        cout << "Invalid number!" << endl;
        return;
    }

    cout << "Enter text: ";
    getline(cin, line);

    st.announce[num] = line;

    ofstream file("announcement.txt");
    if (!file.is_open())
    {
        cout << "Cannot create file!" << endl;
        return;
    } 

    if (!(file << st))
    {
        cout << "Cannot write to file!" << endl;
    }
}

void read_announcement()
{
    student st;
    int num;

    cout << "Enter number: ";
    cin >> num;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    if ((num < 0) || (num >= 10))
    {
        cout << "Invalid number!" << endl;
        return;
    }

    ifstream file("announcement.txt");
    if (!file.is_open())
    {
        cout << "Cannot open file!" << endl;
        return;
    }

    if (!(file >> st))
    {
        cout << "Cannot read from file!" << endl;
        return;
    }

    cout << "Text: " << st.announce[num] << endl;
}

Alternatively: 或者:

struct student
{
    string announce[10];
};

ostream& operator<<(ostream &os, const student &st)
{
    for(int x = 0; x < 10; ++x)
    {
        uint32_t len = st.announce[x].size();
        os.write(reinterpret_cast<char*>(&len), sizeof(len));
        os.write(st.announce[x].c_str(), len);
    }
    return os;
}

istream& operator>>(istream &is, student &st)
{
    for(int x = 0; x < 10; ++x)
        st.announce[x].clear();

    for(int x = 0; x < 10; ++x)
    {
        uint32_t len;
        if (!is.read(reinterpret_cast<char*>(&len), sizeof(len))) break;
        string s;
        if (len > 0)
        {
            s.resize(len);
            if (!is.read(&s[0], len)) break;
        }
        st.announce[x] = s;
    }

    return is;
}

void write_announcement()
{
    student st;
    string line;
    int num;

    cout << "Enter number: ";
    cin >> num;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    if ((num < 0) || (num >= 10))
    {
        cout << "Invalid number!" << endl;
        return;
    }

    cout << "Enter text: ";
    getline(cin, line);

    st.announce[num] = line;

    ofstream file("announcement.txt", ofstream::binary);
    if (!file.is_open())
    {
        cout << "Cannot create file!" << endl;
        return;
    } 

    if (!(file << st))
    {
        cout << "Cannot write to file!" << endl;
    }
}

void read_announcement()
{
    student st;
    int num;

    cout << "Enter number: ";
    cin >> num;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    if ((num < 0) || (num >= 10))
    {
        cout << "Invalid number!" << endl;
        return;
    }

    ifstream file("announcement.txt", ifstream::binary);
    if (!file.is_open())
    {
        cout << "Cannot open file!" << endl;
        return;
    }

    if (!(file >> st))
    {
        cout << "Cannot read from file!" << endl;
        return;
    }

    cout << "Text: " << st.announce[num] << endl;
}

That being said, you are creating a new local student every time you write/read the file, but you populate only 1 string on each write, and are not preserving previous strings across multiple writes. 话虽这么说,您每次写入/读取文件时都在创建一个新的本地student ,但是每次写入仅填充一个字符串,并且不会在多次写入中保留以前的字符串。 So, either: 因此,要么:

  1. read the file to load previous strings before then assigning and writing new strings. 在分配和写入新字符串之前,请先读取文件以加载先前的字符串。

  2. make the student be a global variable so it exists longer than any single write/read operation, and thus can cache string assignments over time. 使student成为全局变量,因此它的存在时间比任何单个写/读操作的时间都长,因此可以随时间缓存字符串分配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM