Почему это исключение появляется при чтении файла, а не при его сохранении? - PullRequest
0 голосов
/ 12 апреля 2019

В настоящее время я работаю над проектом с MFC, и я заметил кое-что странное, что, очевидно, было там в течение нескольких лет.Когда я запускаю .exe программы, она делает n разных вещей, включая чтение файла .DAT и его сохранение.Если файл не существует, программа попытается найти его, но безуспешно выдает это исключение CFile: файл не найден.Что правильно, потому что его не существует.Сначала мне нужно выполнить некоторые операции для генерации этого файла, процесс сохранения работает нормально.Когда файл существует, и я снова запускаю программу, он должен прочитать файл, но появляется это исключение CArchive: Неверный формат файла.И я не понимаю, почему.

Это Serialize ():

//Fruits.cpp

void CFruits::Serialize(CArchive &ar)
{
    int nVersion = 0;
    CObject::Serialize(ar);
    ar.SerializeClass(GetRuntimeClass());

    if(ar.IsStoring())
    {
        ar.Write(&m_bInit,sizeof(bool));            
        ar.Write(&m_bYummy,sizeof(bool));
        ar.Write(&m_bAcid, sizeof(bool));   
        ar.Write(&m_bFresh,sizeof(bool));
        ...
        ...
        ...
        ar<<m_cType;    
        ar<<m_cColour;
        ar<<m_cFlavor;  
        ar<<m_cPrice;   
        ar<<m_cQuantity;
    }
    else
    {
        nVersion = ar.GetObjectSchema();
        ar.Read(&m_bInit,sizeof(bool));     
        ar.Read(&m_bYummy,sizeof(bool));
        ar.Read(&m_bAcid, sizeof(bool));    
        ar.Read(&m_bFresh,sizeof(bool));    
        ...
        ...
        ...

        if( nVersion >= 2 || nVersion < 0)
            ar<<m_cType;
        else
            m_cType=0;

        if (nVersion >= 3 || nVersion < 0)
            ar<<m_cColour;
        else
            m_cColour=0;

        if (nVersion >= 4 || nVersion < 0)
            ar<<m_cFlavor;  
        else
            ar<<m_cFlavor=0;

        if( nVersion >= 5 || nVersion < 0)
        {
            ar<<m_cPrice;   
            ar<<m_cQuantity;
        }
        else
        {
            m_cPrice=0; 
            m_cQuantity=0;
        }            
    }

    m_oSales.Serialize(ar);     
    m_oAdmin.Serialize(ar);     
    ...
    ...     
}

IMPLEMENT_SERIAL(CVehiculo,CObject,VERSIONABLE_SCHEMA | 6)

Это SerializeElements:

//Fruits.cpp

void AFXAPI SerializeElements(CArchive &ar,CFruits * fruits,int ncount)
{
    try
    {
        for(cont=0;cont<ncount;cont++)
            fruits[cont].Serialize(ar);

    }
    catch(CArchiveException *AE)
    {
        //Here it stores the exception in a Log. Exception 5
    }
}

serializeElements используется для храненияи прочитайте файл n раз, как указано здесь в заголовочном файле фруктов:

//Fruits.h

class CFruits : public CObject
{
public:
    CFruits();
    CFruits(const CFruits &O);
    virtual ~CFruits();
    void operator = (const CFruits &O);
    void        Serialize(CArchive &ar);

protected:
    DECLARE_SERIAL(CFruits)
};

void AFXAPI SerializeElements(CArchive &ar,CFruits * fruits,int ncount);

typedef CArray<CFruits, CFruitso&> TArrayFruits;

Значения этого массива и методы, используемые для вызова сериализации, определены здесь в моей главной функции:

//main.h

#include "CFruits.h"

class CMain : public CDialog 
{
// Construction
public:

    enum T_Fruits { eFruitsOnLine, eFruitsIng, eFruitsTra, eFruitsAnt, eFruitsP3, eFruitsP2, eFruitsP1, eFruitsC1, eFruitsC0, eFruitsEscape, eFruitsVideo};

private:

    void            StoreFruits();
    void            ReadFruits();

Предполагается, что цикл for SerializeElements должен выполняться 11 раз, но я заметил, что он делает это только 1 раз, затем версия схемы изменяется на -1 (изначально 6, потому что мне удалось отследить значение),Это происходит только при чтении файла.Я пробовал следующее: я не могу использовать отладку, поэтому я должен использовать журналы, я помещал журнал после каждого предложения в функцию Serialize (), я нашел, что, кажется, проблема, эту строку:

ar.SerializeClass(GetRuntimeClass());

Я использовал try-catch и обнаружил, что когда это предложение происходит, оно выдает исключение, поэтому оно не продолжает читать.Это момент, когда версия меняется на -1.Я попытался изменить это на:

ar.SerializeClass(RUNTIME_CLASS(CFruits));

Это тот же результат, я прочитал много фрум, пытаясь найти ответ, но я не могу этого сделать.Я прочитал документацию и нашел ее здесь: https://docs.microsoft.com/en-us/cpp/mfc/reference/carchive-class?view=vs-2019#serializeclass

Как и ReadClass, SerializeClass проверяет, что информация о заархивированном классе совместима с вашим классом времени выполнения.Если он несовместим, SerializeClass сгенерирует исключение CArchiveException.

Но это не имеет смысла для меня, потому что оно не перестает хранить.Стоит ли искать что-то еще?

Спасибо

РЕДАКТИРОВАТЬ: я публикую методы Store и Read

void CMain::ReadFruits()
{
    CString CSerror, sFileName;
    CString sDebug;

    try
    {
        sFileName.Format("FRUITS%03d.DAT",GetNumT());
        CFile fFruitsTag(sFileName,CFile::modeRead);
        CArchive ar(&fFruitsTag,CArchive::load);
        m_vFruits.Serialize(ar);
        ar.Close();
        fFruitsTag.Close();
    }
    catch(CFileException *FE)
    {
        ...
    }
    catch(CArchiveException *AE)
    {
        ...
    }
}

void CMain::StoreFruits()
{
    CString CSerror, sFileName;

    try
    {
        if(!m_bStoringFruits)
        {
            sFileName.Format("FRUITS%03d.DAT",GetNumT());
            m_bStoringFruits=true;
            CFile fFruitsTag(sFileName,CFile::modeCreate|CFile::modeWrite);
            CArchive ar(&fFruitsTag,CArchive::store);
            m_vFruits.Serialize(ar);
            ar.Close();
            fFruitsTag.Close();
            m_bStoringFruits=false;
        }
    }
    catch(CFileException *FE)
    {
        ...
    }
    catch(CArchiveException *AE)
    {
        ...
    }
    catch(CException *e)
    {       
        ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...