当我从文件中加载序列化时,为啥我的向量充满结构的大小如此之大?

Posted

技术标签:

【中文标题】当我从文件中加载序列化时,为啥我的向量充满结构的大小如此之大?【英文标题】:Why is the size of my vector full of structs so large when I load it's serialization in from a file?当我从文件中加载序列化时,为什么我的向量充满结构的大小如此之大? 【发布时间】:2009-04-02 07:38:16 【问题描述】:

正如你们中的大多数人可能已经知道我的一系列问题一样,我正在尝试创建一个程序,该程序可以将多个结构序列化为 .dat 文件,通过加载序列化将它们读回,编辑内容,然后然后将它们重新写入文件等等。这是我正在尝试做的一个库存计划,但我无法让它终生发挥作用。

我正在加载的文件是空白的。我的程序甚至需要 10 秒才能加载,现在我知道为什么了。这是因为我的向量的大小是 25 万。哦等等……这次我运行它,我的向量大小是 5,172,285。那是一个非常大的充满结构的向量。没有任何运行时或编译错误,但我很确定我做错了什么。我正在加载的文件也是完全空白的。

代码:

// Project 5.cpp : main project file.

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

using namespace System;
using namespace std;
#pragma hdrstop

int checkCommand (string line);

template<typename T>
void writeVector(ofstream &out, const vector<T> &vec);

template<typename T>
vector<T> readVector(ifstream &in);

struct InventoryItem 
    string Item;
    string Description;
    int Quantity;
    int wholesaleCost;
    int retailCost;
    int dateAdded;
 ;


int main(void)

    cout << "Welcome to the Inventory Manager extreme! [Version 1.0]" << endl;
    ifstream in("data.dat");
    if (in.is_open())  cout << "File \'data.dat\' has been opened successfully." << endl;  else  cout << "Error opening data.dat" << endl; return 0;
    cout << "Loading data..." << endl;
    vector<InventoryItem> structList = readVector<InventoryItem>( in );
    cout <<"Load complete." << endl;

    while (1)
    

        string line = "";
        cout << "There are currently " << structList.size() << " items in memory.";
        cout << endl;
        cout << "Commands: " << endl;
        cout << "1: Add a new record " << endl;
        cout << "2: Display a record " << endl;
        cout << "3: Edit a current record " << endl;
        cout << "4: Exit the program " << endl;
        cout << endl;
        cout << "Enter a command 1-4: ";

        getline(cin , line);


        int rValue = checkCommand(line);
        if (rValue == 1)
        
            cout << "You've entered a invalid command! Try Again." << endl;
         else if (rValue == 2) 
            cout << "Error calling command!" << endl;
         else if (!rValue) 
            break;
        
    


    system("pause");

    return 0;


int checkCommand (string line)

    int intReturn = atoi(line.c_str());
    int status = 3;

    switch (intReturn)
    
        case 1:
            break;
        case 2:
            break;
        case 3:
            break;
        case 4:
            status = 0;
            break;
        default:
            status = 1;
            break;
    
    return status;


template<typename T>
void writeVector(ofstream &out, const vector<T> &vec)

    out << vec.size();

    for(vector<T>::const_iterator i = vec.begin(); i != vec.end(); i++)
    
        out << *i;
    


ostream &operator<<(ostream &out, const InventoryItem &i)

    out << i.Item << i.Description;
    out << i.Quantity;
    out << i.wholesaleCost << i.retailCost;
    out << i.dateAdded;
    return out;


istream &operator>>(istream &in, InventoryItem &i)

    in >> i.Item >> i.Description;
    in >> i.Quantity;
    in >> i.wholesaleCost >> i.retailCost;
    in >> i.dateAdded;
    return in;




template<typename T>
vector<T> readVector(ifstream &in)

    size_t size;
    in >> size;

    vector<T> vec;
    vec.reserve(size);

    for(unsigned int i = 0; i < size; i++)
    
        T tmp;
        in >> tmp;
        vec.push_back(tmp);
    

    return vec;

谁能简单地告诉我如何将其转换为一个程序,该程序实际上可以将充满结构的序列化向量写入文件,然后将它们读回,以便我可以编辑它们并将它们存储回去以供以后加载?哦,我的天哪,这是一次多么愉快的旅程!

感谢您提供的任何帮助!

【问题讨论】:

最好自己做作业 关于作业主题的问题可以提问,礼仪不是解决问题的全部,只是针对问题给出提示和建议。如果在您尝试学习时根本没有任何帮助,这可能会令人沮丧 【参考方案1】:

你说文件实际上是空的。 readVector 的第一行是这样的:

in >> size;

你认为最终的尺寸会是多少?由于它是空的,这将导致您没有检测到的错误。变量size 将保持未初始化状态 - 因此您会在其中看到奇怪的值,因为它采用了当时内存中发生的任何值。您可以使用检查来检查流的状态:

if (in)

在布尔上下文中处理它会告诉您是否发生错误 - 这也将涵盖诸如无法读取有效整数变量之类的问题。我建议您应该弄清楚如何在调试器中运行您的程序,您将能够单步执行您的代码并查看给定时间变量的值。

【讨论】:

我试过 if (in) in >> size; 其他 大小 = 0;但我仍然遇到同样的问题。这是您建议的解决方法吗? 不完全是。错误状态是在您尝试从流中读取之后设置的,而不是之前 那是什么意思? 更准确地说,在您完成in &gt;&gt; size 行(或尝试从流中读取任何其他类型)之后,设置了错误状态 - 您应该在每次尝试读取后检查状态【参考方案2】:

所以如果你的文件是空白的并且你正在做:

size_t size;
in >> size;

vector<T> vec;
vec.reserve(size);

你认为会发生什么?大小无法读取,使用随机值

【讨论】:

如何防止这种情况发生? 查看 1800 INFORMATION 帖子和 cmets【参考方案3】:

如果您的输入文件为空,则vector 应为空。你不应该越界:

if (in.is_open()) 

-- 你的程序(当我在我的机器上运行它时)退出。

你能解释一下为什么会有以下问题吗?

#include <String>

using namespace System;

#pragma hdrstop

最容易实现的是一次性读入文件内容,将项目保存在内存中,在内存中编辑它们,然后通过编辑一次写入文件。从内存占用或性能的角度来看,这当然不是一个很好的技术。但是,您要解决的问题并非微不足道。阅读FAQ 36 以更好地了解您的任务。

【讨论】:

哦,废话。那是因为文件开头的 if(file.is_open) 抱歉【参考方案4】:

您正在使用空白文件,但是当您加载文件时,您正在寻找一个大小。当文件在文件中没有大小时,您可能会将垃圾放入您的大小变量中。

所以尝试在“data.dat”文件的第一行输入一个零。

编辑: 上述建议只是一个临时修复。你可以试试这个:

in >> size;
//input operation failed
if(in.fail())
    //return, or whatever you need to do

【讨论】:

我认为这可能不太对,编写代码以使其可以处理空文件不是更好吗? 我同意。我更建议将其作为临时解决方案...我应该提到这一点。糟糕! 谢谢你,这就是我的要求。我添加了它,它起作用了。

以上是关于当我从文件中加载序列化时,为啥我的向量充满结构的大小如此之大?的主要内容,如果未能解决你的问题,请参考以下文章

在Android中加载大文本

在 j2me 中加载屏幕

当我尝试在 Android NDK 中加载冻结模型时,为啥没有注册操作?

Google BigQuery:当我从存储中加载数据时出现“string_field_0”

从文件中加载对象的 ArrayList [重复]

为啥偶尔会在 ListView 中加载错误的图像?