Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Problem Reading/Writing text/dat files

Problem Reading/Writing text/dat files

Scheduled Pinned Locked Moved C / C++ / MFC
helpdatabasetutorial
16 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T ThatsAlok

    just a basic question, why don't use simple CStdioFile or CFile classes when you are building MFC app instead of raw api CreateFile. though i am big fan window api! just a thought !

    T Offline
    T Offline
    Trupti Mehta
    wrote on last edited by
    #7

    Alok, this application is especially meant for development in eVC++ with WinCe. CStudioFile is not supported. So got to opt raw api of C/C++.

    Thanks Terry

    T 1 Reply Last reply
    0
    • T Trupti Mehta

      Alok, this application is especially meant for development in eVC++ with WinCe. CStudioFile is not supported. So got to opt raw api of C/C++.

      Thanks Terry

      T Offline
      T Offline
      ThatsAlok
      wrote on last edited by
      #8

      just a question are ATL header files are available for eVC, you could use CAtlFile Class [^]

      T 1 Reply Last reply
      0
      • T Trupti Mehta

        Oh Thaks Mark, this helped me get rid of the Assertion Errors/Exceptions. But still my condition hasn't improved, its in almost same place. I store 2 objs in a map & send it to write.

        newOperMap.SetAt(1, OperatorDetails(1, \_T("One")));
        newOperMap.SetAt(2, OperatorDetails(2, \_T("Two")));
        db.WriteOperators(newOperMap);
        

        Write method

        	for (POSITION pos = opdtMap.GetStartPosition(); pos != NULL;) {
        		int key;
        		OperatorDetails od;
        		opdtMap.GetNextAssoc(pos, key, od ); 
        

        // ar.WriteObject(&od);
        ar << &od;
        }

        Executes for loop 2 times, od has respectives values i.e. "Two" followed by "One". In my text file, I can see only "Two":

         ÿÿ
         OperatorDetails Two

        While Reading:

        		OperatorDetails\* od;
        	
        	for (int i=0; i < count; i++) {
        		OperatorDetails odObj;
        		ar >> od;
        		if (od == NULL)
        			break;
        		
        		odObj.SetOperatorNo(od->GetOperatorNo());
        		odObj.SetOperName(od->GetOperName());
        		operMap->SetAt(odObj.GetOperatorNo(), odObj);
        	}
        		delete od;
        

        For loop executes twice as count is stored as 2 records while writing. Both the times it gets only "Two". So number of records actually retrieved are only 1 as the key is the same 2. While writing though &od has the proper object 2nd time i.e. 1 One, still it doesn't write only. ar << &od is also executing properly, still somehow something is acting weird. Can you help me figure out that improper stuff. Would be glad enough & able to take a relaxed breath.

        Thanks Terry

        M Offline
        M Offline
        Mark Salsbery
        wrote on last edited by
        #9

        First, I would change the CMap ARG_KEY and ARG_VALUE types to references:

        CMap<int, int&, OperatorDetails, OperatorDetails&>

        Second, can you post the OperatorDetails::Serialize() code? Mark

        Mark Salsbery Microsoft MVP - Visual C++ :java:

        T 1 Reply Last reply
        0
        • T Trupti Mehta

          Oh Thaks Mark, this helped me get rid of the Assertion Errors/Exceptions. But still my condition hasn't improved, its in almost same place. I store 2 objs in a map & send it to write.

          newOperMap.SetAt(1, OperatorDetails(1, \_T("One")));
          newOperMap.SetAt(2, OperatorDetails(2, \_T("Two")));
          db.WriteOperators(newOperMap);
          

          Write method

          	for (POSITION pos = opdtMap.GetStartPosition(); pos != NULL;) {
          		int key;
          		OperatorDetails od;
          		opdtMap.GetNextAssoc(pos, key, od ); 
          

          // ar.WriteObject(&od);
          ar << &od;
          }

          Executes for loop 2 times, od has respectives values i.e. "Two" followed by "One". In my text file, I can see only "Two":

           ÿÿ
           OperatorDetails Two

          While Reading:

          		OperatorDetails\* od;
          	
          	for (int i=0; i < count; i++) {
          		OperatorDetails odObj;
          		ar >> od;
          		if (od == NULL)
          			break;
          		
          		odObj.SetOperatorNo(od->GetOperatorNo());
          		odObj.SetOperName(od->GetOperName());
          		operMap->SetAt(odObj.GetOperatorNo(), odObj);
          	}
          		delete od;
          

          For loop executes twice as count is stored as 2 records while writing. Both the times it gets only "Two". So number of records actually retrieved are only 1 as the key is the same 2. While writing though &od has the proper object 2nd time i.e. 1 One, still it doesn't write only. ar << &od is also executing properly, still somehow something is acting weird. Can you help me figure out that improper stuff. Would be glad enough & able to take a relaxed breath.

          Thanks Terry

          M Offline
          M Offline
          Mark Salsbery
          wrote on last edited by
          #10

          Trupti Mehta wrote:

          for (POSITION pos = opdtMap.GetStartPosition(); pos != NULL [Wink] { int key; OperatorDetails od; opdtMap.GetNextAssoc(pos, key, od ); // ar.WriteObject(&od); ar << &od; }

          I tested this and traced into the MFC code to see why only one object was getting written to the archive. There's an "optimization" in there - if the CObject* serialized with WriteObject() (or ar << &od;, which calls WriteObject()) matches a CObject* that's already been written to the archive, then just a reference to the original serialized object is written to the archive. Since the above code is passing the same pointer (a pointer to the same object) each time, the first object found gets serialized, then only references to that first object are written. FWIW, here's an example of the correct way to serialize/unserialize a CMap:

          typedef CMap<int, int, OperatorDetails, OperatorDetails&> OperatorDetailsMap;

          template <> void AFXAPI SerializeElements <OperatorDetails> (CArchive &ar, OperatorDetails *pOperatorDetails, INT_PTR nCount)
          {
          for (int i = 0; i < nCount; i++, pOperatorDetails++)
          {
          pOperatorDetails->Serialize(ar);
          }
          }

          void WriteArchive()
          {
          OperatorDetailsMap newOperMap;
          newOperMap.SetAt(1, OperatorDetails(1, _T("One")));
          newOperMap.SetAt(2, OperatorDetails(2, _T("Two")));

          CFile myfile(\_T("e:\\\\archive\_test.txt"), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite);
          CArchive ar(&myfile, CArchive::store);   
          
          newOperMap.Serialize(ar);
          
          ar.Close();
          myfile.Close();
          

          }

          void ReadArchive()
          {
          OperatorDetailsMap newOperMap;

          CFile myfile(\_T("e:\\\\archive\_test.txt"), CFile::modeRead | CFile::shareDenyNone);
          CArchive ar(&myfile, CArchive::load);   
          
          newOperMap.Serialize(ar);
          
          ar.Close();
          myfile.Close();
          

          }

          Mark Salsbery Microsoft MVP - Visual C++ :java:

          T 1 Reply Last reply
          0
          • M Mark Salsbery

            Trupti Mehta wrote:

            for (POSITION pos = opdtMap.GetStartPosition(); pos != NULL [Wink] { int key; OperatorDetails od; opdtMap.GetNextAssoc(pos, key, od ); // ar.WriteObject(&od); ar << &od; }

            I tested this and traced into the MFC code to see why only one object was getting written to the archive. There's an "optimization" in there - if the CObject* serialized with WriteObject() (or ar << &od;, which calls WriteObject()) matches a CObject* that's already been written to the archive, then just a reference to the original serialized object is written to the archive. Since the above code is passing the same pointer (a pointer to the same object) each time, the first object found gets serialized, then only references to that first object are written. FWIW, here's an example of the correct way to serialize/unserialize a CMap:

            typedef CMap<int, int, OperatorDetails, OperatorDetails&> OperatorDetailsMap;

            template <> void AFXAPI SerializeElements <OperatorDetails> (CArchive &ar, OperatorDetails *pOperatorDetails, INT_PTR nCount)
            {
            for (int i = 0; i < nCount; i++, pOperatorDetails++)
            {
            pOperatorDetails->Serialize(ar);
            }
            }

            void WriteArchive()
            {
            OperatorDetailsMap newOperMap;
            newOperMap.SetAt(1, OperatorDetails(1, _T("One")));
            newOperMap.SetAt(2, OperatorDetails(2, _T("Two")));

            CFile myfile(\_T("e:\\\\archive\_test.txt"), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite);
            CArchive ar(&myfile, CArchive::store);   
            
            newOperMap.Serialize(ar);
            
            ar.Close();
            myfile.Close();
            

            }

            void ReadArchive()
            {
            OperatorDetailsMap newOperMap;

            CFile myfile(\_T("e:\\\\archive\_test.txt"), CFile::modeRead | CFile::shareDenyNone);
            CArchive ar(&myfile, CArchive::load);   
            
            newOperMap.Serialize(ar);
            
            ar.Close();
            myfile.Close();
            

            }

            Mark Salsbery Microsoft MVP - Visual C++ :java:

            T Offline
            T Offline
            Trupti Mehta
            wrote on last edited by
            #11

            tHANKS mARK. I appreciate your efforts and help towards my problem. The above code works perfectly with Visual Studio. But when I added in eVC++, I am getting Linker errors. Code is added & implemented in the same way in VS & eVC++. I added the above code in my DbOperations class - SerializeElements is not a member of DbOperations, just added in the class cpp file. And from another dialog class Operator, I am calling db.WriteArchive() & ReadArchive(). From my view class, via a menu Operator.doModal is called, so view class is also in the picture. I get the following errors:

            Linking...
            MC_AppView.obj : error LNK2005: "void __cdecl SerializeElements(class CArchive &,class OperatorDetails *,int)" (?SerializeElements@@YAXAAVCArchive@@PAVOperatorDetails@@H@Z) already defined in DbOperations.obj
            Operator.obj : error LNK2005: "void __cdecl SerializeElements(class CArchive &,class OperatorDetails *,int)" (?SerializeElements@@YAXAAVCArchive@@PAVOperatorDetails@@H@Z) already defined in DbOperations.obj
            ARMV4IDbg/MC_App.exe : fatal error LNK1169: one or more multiply defined symbols found
            Error executing link.exe.

            I tried making SerializeElemnets as a member of DbOperations, but that also gives lots of errors due to <>, etc. How do I avoid these errors?

            Thanks Terry

            T 1 Reply Last reply
            0
            • T ThatsAlok

              just a question are ATL header files are available for eVC, you could use CAtlFile Class [^]

              T Offline
              T Offline
              Trupti Mehta
              wrote on last edited by
              #12

              No Alok, ATL is not available in eVC, only MFC & pure C/C++. In that too with Win CE, many are again not allowed or supported.

              Thanks Terry

              1 Reply Last reply
              0
              • M Mark Salsbery

                First, I would change the CMap ARG_KEY and ARG_VALUE types to references:

                CMap<int, int&, OperatorDetails, OperatorDetails&>

                Second, can you post the OperatorDetails::Serialize() code? Mark

                Mark Salsbery Microsoft MVP - Visual C++ :java:

                T Offline
                T Offline
                Trupti Mehta
                wrote on last edited by
                #13

                My Serialize code is :

                // Serialize
                void OperatorDetails::Serialize(CArchive &ar)
                {
                if (ar.IsStoring())
                ar << operNo << operName;
                else
                ar >> operNo >> operName;

                }

                And the linker error says (the part that is cut for view.obj & Operator.obj) already defined in DbOperations.obj

                Thanks Terry

                1 Reply Last reply
                0
                • T Trupti Mehta

                  tHANKS mARK. I appreciate your efforts and help towards my problem. The above code works perfectly with Visual Studio. But when I added in eVC++, I am getting Linker errors. Code is added & implemented in the same way in VS & eVC++. I added the above code in my DbOperations class - SerializeElements is not a member of DbOperations, just added in the class cpp file. And from another dialog class Operator, I am calling db.WriteArchive() & ReadArchive(). From my view class, via a menu Operator.doModal is called, so view class is also in the picture. I get the following errors:

                  Linking...
                  MC_AppView.obj : error LNK2005: "void __cdecl SerializeElements(class CArchive &,class OperatorDetails *,int)" (?SerializeElements@@YAXAAVCArchive@@PAVOperatorDetails@@H@Z) already defined in DbOperations.obj
                  Operator.obj : error LNK2005: "void __cdecl SerializeElements(class CArchive &,class OperatorDetails *,int)" (?SerializeElements@@YAXAAVCArchive@@PAVOperatorDetails@@H@Z) already defined in DbOperations.obj
                  ARMV4IDbg/MC_App.exe : fatal error LNK1169: one or more multiply defined symbols found
                  Error executing link.exe.

                  I tried making SerializeElemnets as a member of DbOperations, but that also gives lots of errors due to <>, etc. How do I avoid these errors?

                  Thanks Terry

                  T Offline
                  T Offline
                  Trupti Mehta
                  wrote on last edited by
                  #14

                  Mark, I removed the template <> SerializeElements() from the code & ran the application. Its still running and giving the results as we expected, but after reading is completed, it throws Assertion Failure: on strcode.cpp Line 171 which falls under void CString::Release(), ASSERT(GetData()->nRefs != 0); line. If I do retry, it works properly. I need to get rid of this error. Do you know how to I catch exception in eVC++. If I write try{ .... } catch(CException e) { } it shows warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX. The MSDN warning lists of 4530 mentions to specify /EHsc. How do I speicify any of this & where in the Project Settings. This will be a great help, as I like very much to catch exception and handle them. But in eVC I am not able to do it due to these errors/warnings. Please would be nice if can help out in this.

                  Thanks Terry

                  M 1 Reply Last reply
                  0
                  • T Trupti Mehta

                    Mark, I removed the template <> SerializeElements() from the code & ran the application. Its still running and giving the results as we expected, but after reading is completed, it throws Assertion Failure: on strcode.cpp Line 171 which falls under void CString::Release(), ASSERT(GetData()->nRefs != 0); line. If I do retry, it works properly. I need to get rid of this error. Do you know how to I catch exception in eVC++. If I write try{ .... } catch(CException e) { } it shows warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX. The MSDN warning lists of 4530 mentions to specify /EHsc. How do I speicify any of this & where in the Project Settings. This will be a great help, as I like very much to catch exception and handle them. But in eVC I am not able to do it due to these errors/warnings. Please would be nice if can help out in this.

                    Thanks Terry

                    M Offline
                    M Offline
                    Mark Salsbery
                    wrote on last edited by
                    #15

                    Trupti Mehta wrote:

                    I removed the template <> SerializeElements() from the code & ran the application. Its still running and giving the results as we expected,

                    That won't work well with CStrings in the OperatorDetails class, since without a SerializeElements() override for the CMap, the default serialization of the map's objects is binary bits - not good when pointers are involved :) I'm not sure why the template function causes the link to fail.  You should be able to put the SerializeElements() template in ONE cpp file and it should work.  I tested with it in the same CPP file that does the serialization/unserialization of the CMap (just above my sample WriteArchive() and ReadArchive functions). Mark

                    Mark Salsbery Microsoft MVP - Visual C++ :java:

                    T 1 Reply Last reply
                    0
                    • M Mark Salsbery

                      Trupti Mehta wrote:

                      I removed the template <> SerializeElements() from the code & ran the application. Its still running and giving the results as we expected,

                      That won't work well with CStrings in the OperatorDetails class, since without a SerializeElements() override for the CMap, the default serialization of the map's objects is binary bits - not good when pointers are involved :) I'm not sure why the template function causes the link to fail.  You should be able to put the SerializeElements() template in ONE cpp file and it should work.  I tested with it in the same CPP file that does the serialization/unserialization of the CMap (just above my sample WriteArchive() and ReadArchive functions). Mark

                      Mark Salsbery Microsoft MVP - Visual C++ :java:

                      T Offline
                      T Offline
                      Trupti Mehta
                      wrote on last edited by
                      #16

                      Mark, I also have added in the same file (DbOperations.cpp) just copied your code same way. All serialization.desera & template overrride are in the same file. I tried removing template<> & AFXAPI, but still no success. You were very correct that with pointers of Map I will have a problem. To pass the DbOperations reference to other classes, I made a copy constructor & operator=, in this case I can't directly copy map tp map. So I made operatorMap as pointer & the other map deptMap is as a normal object only & not assigning in copy constru or =. deptMap additions & updations are possible (NOT a pointer), but operatorMap (a POINTER) operations are not allowed. It causes Assertion failure in afxtempl.h line 1368 which is Assert 1st line of CMap<> operator[]. I got to take out some solution of this. Can you tell how to assign a map to map in copy constructr & = operator. Basically copy a map to other. In DbOperations .h

                      typedef CMap<int, int, OperatorDetails, OperatorDetails&> OperatorDetailsMap;
                      typedef CMap<int, int, DeptDetails, DeptDetails&> DeptDetailsMap;

                      class ....{
                      // MAPS
                      OperatorDetailsMap* operMap;
                      DeptDetailsMap deptMap;

                      In .cpp
                      // Copy Constructor
                      DbOperations::DbOperations(const DbOperations &d) {
                      this->operMap = d.operMap;
                      // this->deptMap = d.deptMap;
                      }
                      // = Assignment operator
                      DbOperations& DbOperations::operator=(const DbOperations &d) {
                      this->operMap = d.operMap;
                      // this->deptMap = d.deptMap;

                      return \*this;
                      

                      }
                      /*template <> void AFXAPI SerializeElements <OperatorDetails> (CArchive &ar, OperatorDetails *pOperatorDetails, INT_PTR nCount){
                      for (int i = 0; i < nCount; i++, pOperatorDetails++) {
                      pOperatorDetails->Serialize(ar);
                      }
                      }*/

                      My point is how do I copy this.deptMap with d.deptMap, where deptMap being normal objects & not a pointer. With this solution we wont have problem with serializeElements() & pointers. As SerializeElements() causes problems, so looking out for solution without serializeElements & pointers. SerializeElemtsis added only in DbOperations along with WriteArchive & ReadArchive. The same thing is working with Visual Studio, but not with eVC++4. Really it is difficult to code in eVC++ than VC++, many restrictions & uncompatibility. Looking for solution as soon as possible. From days I have been looking for this solution & yet not solved. You have been extremely helpful throughout. I highly appreciate your help and look towards more help. <

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups