zapis wektora do pliku

0

Cześć,
próbuję napisać kod zapisujący wektor do pliku, program tworzy plik "materials.dat", jednak po ponownym uruchomieniu nieoczekiwanie kończy działanie. Nie działa poprawnie komenda plik.read.
Czy można zapisywać wektor w całości? Na niektórych forach wyczytałem, że trzeba zapisywać każdy element osobno, na innych że nie trzeba, ale w jaki sposób odczytywać później te elementy z pliku?

 
(...)
using namespace std;
typedef vector<Substance> SubstanceList;
SubstanceList SubsList;

        ifstream plik("materials.dat",ios::binary);
        if (!plik) {
            Substance Subs;
            Subs.setDensity(1000);
            Subs.setName("Proba");

            SubsList.push_back(Subs);

            ofstream fout("materials.dat", ios::binary);
            fout.write((char*) &SubsList, sizeof(SubsList));
            fout.close();

        } else {

    plik.read((char*) &SubsList, sizeof(SubsList));
(...)
}
0

Tak prosto to się nie da ;) Poczytaj sobie o serializacji klas. Zapewne pod tym hasłem znajdziesz na tym forum rozwiązanie problemu, bo był 5168726 razy.

0

Dzięki, wyszukałem sposób z biblioteka boost_serialization na stronie (odpowiedź 4):
http://stackoverflow.com/questions/2469531/reading-and-writing-c-vector-to-a-file

problem jest teraz taki, że we fragmencie

namespace boost {
namespace serialization {
    template<class Archive>
    void serialize(Archive & ar, Vertex& v, const unsigned int version)
    {
ar & v.x; 
ar & v.y; 
ar & v.z;
    }
} }

dostęp do zmiennych obiektu v jest publiczny, u mnie jest przez akcesory i nie wiem jak to zapisać...

0

a nie łatwiej zapisać najpierw liczbę elementów, a potem każdy element po kolei? albo nawet bez liczby elementów

0

Może pokaż definicję klasy Substance.

0
 
class Substance
{
      public:
             QString getName() const {return itsName; }
             void getElasticity((float&) Elasticity[6][6]) const;
             float getDensity() const { return itsDensity; }
             void setName(QString N) { itsName = N; }
             void setElasticity((float&) Elasticity[6][6]);
             void setDensity(float D) { itsDensity = D; }
      private:
              QString itsName;
              float itsElasticity[6][6];
              float itsDensity;
};

Chodzi o to, że nie mogę napisać
ar &Subs.itsDensity;

ale też nie jest poprawne

ar &Subs.getDensity();

0
class Substance
{
public:
	ostream& Save(ostream &os)
	{
		/* tu zapisujesz klamoty */
		
		return os;
	}
	
	istream& Load(istream &is)
	{
		/* tu je czytasz */
		
		return is;
	}

	...
};

/* zapis */
int n = SubsList.size();

fout.write((char*) &n, sizeof(int));
 
for(int i = 0; i < n; ++i)
	SubsList[i].Save(fout);	

/* odczyt */
int n;

if(fin.read((char*) &n, sizeof(int)))
{ 
	SubsList.resize(n);

	for(int i = 0; i < n && SubsList[i].Load(fin); ++i);
}

A nie możesz zrobić tak, bez boosta?

0

Próbowałem tak :/ niestety w windowsie podczas wykonywania programu (odczytywania pliku) wyskakuje błąd aplikacji "Instrukcja spod(...) odwołuje się do (...). Pamięć nie może być read".

0

No to jeśli próbowałeś, to pokaż kod.

0
Anthus napisał(a)

Chodzi o to, że nie mogę napisać
ar &Subs.itsDensity;

ale też nie jest poprawne

ar &Subs.getDensity();
A instrukcja friend oczywiście nie do przyjęcia?

0

Zrobiłem serializację za pomocą boost:

klasy.hpp:

class Substance
{
    friend class boost::serialization::access;
      public:
            Substance();
            Substance (const Substance &);
            ~Substance() {}
             string getName() const {return itsName; }
             QString getQName() const {
                 QString qname( itsName.c_str() );
                 return qname; }
             void getElasticity(float (&Elasticity)[6][6]) const;
             float getDensity() const { return itsDensity; }
             void setName(string N) { itsName = N; }
             void setElasticity(float (&Elasticity)[6][6]);
             void setDensity(float D) { itsDensity = D; }
      public:
              string itsName;
              float itsElasticity[6][6];
              float itsDensity;
};
 

mainwindow.cpp:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

(...)
        ifstream plik("materials.dat",ios::binary);

        if (!plik) {
            SubstanceList SubsList;
            Substance Subs;
            Subs.setName("Ojej");
            Subs.setDensity(1000);

            SubsList.push_back(Subs);

            ofstream fout("materials.dat", ios::binary);
            boost::archive::binary_oarchive oar(fout);
                    oar << SubsList;
            fout.close();

        } else {

        SubstanceList SubsList;
        boost::archive::binary_iarchive iar(plik);
//        iar >> SubsList;
//        plik.close();
        }
}
 

mainwindow.h:

 
typedef vector<Substance> SubstanceList;

namespace boost { namespace serialization {
    template<class Archive>
    void serialize(Archive & ar, Substance& v, const unsigned int version)
    {
        ar & v.itsName;
        ar & v.itsDensity;
        ar & v.itsElasticity[6][6];
    }
} }

Tworzy się plik materials.dat przy pierwszym uruchomieniu, jednak podczas wykonywania polecenia:
iar >> SubsList;
program nieoczekiwanie przerywa pracę.

0

Ok, problem rozwiązałem sposobem 0x666, z tym że trzeba było kolejno zapisać wszystkie wyrazy tablicy i przekształcić "stringi" na tablicę char.

Dziękuję za cierpliwość :)

0

Zapisywać kolejno to już dawno cie powiedziano. Co do konwersji na char * nie ma takiej potrzeby.

0
Anthus napisał(a)

Zrobiłem serializację za pomocą boost:

klasy.hpp:(...)
mainwindow.cpp:(...)
mainwindow.h:(...)

Tworzy się plik materials.dat przy pierwszym uruchomieniu, jednak podczas wykonywania polecenia:
iar >> SubsList;
program nieoczekiwanie przerywa pracę.

Rozwiazales problem, ale jeszcze sie odezwe:)
Zdziwilo mnie to bardzo, poniewaz nigdy dotad z boost::serialization nie mialem zadnych wiekszych problemow, a Twoj kod generalnie wygladal prawidlowo poza jednym drobiazgiem.

Poskladalem u siebie analogiczny, uzupelniajac o rzeczy które wyciałes:

#include <vector>
#include <boost/serialization/serialization.hpp>

class Substance
{
friend class boost::serialization::access;

public:
    ~Substance() {}

    Substance(){ }
    Substance (const Substance & rhs) {itsName = rhs.itsName;itsDensity=rhs.itsDensity;memcpy(itsElasticity,rhs.itsElasticity,sizeof(itsElasticity));}

    std::string getName() const {return itsName; }
    //QString getQName() const { QString qname( itsName.c_str() ); return qname; }
    void setName(std::string N) { itsName = N; }
	
    void getElasticity(float (&Elasticity)[6][6]) const;
    void setElasticity(float (&Elasticity)[6][6]){memcpy(itsElasticity,Elasticity,sizeof(itsElasticity));}
	
    float getDensity() const { return itsDensity; }
    void setDensity(float D) { itsDensity = D; }

public:
    std::string itsName;
    float itsElasticity[6][6];
    float itsDensity;
};
#include <vector>
#include <boost/serialization/serialization.hpp>
#include "klasy.hpp"

typedef std::vector<Substance> SubstanceList;

namespace boost { namespace serialization {
    template<class Archive>
    void serialize(Archive & ar, Substance& v, const unsigned int version)
    {
        ar & v.itsName;
        ar & v.itsDensity;
        ar & v.itsElasticity;   //// (A)
    }
}	}
#include <fstream>
#include <vector>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

#include "main.h"

int main()
{
    using namespace std;

    ifstream plik("materials.dat",ios::binary);  //F

    if (!plik)
    {
        SubstanceList SubsList;
        Substance Subs;
        Subs.setName("Ojej");
        Subs.setDensity(1000);
        float tmp[6][6] = { {1,2,3,4,5,6}, {11,12,13,14,15,16}, {21,22,23,24,25,26}, {31,32,33,34,35,36}, {41,42,43,44,45,46}, {51,52,53,54,55,56}, };
        Subs.setElasticity(tmp);

        SubsList.push_back(Subs);

        ofstream fout("materials.dat", ios::binary);
        boost::archive::binary_oarchive oar(fout);
        oar << SubsList;
        fout.close();    //// (B)
    } else
    {
        SubstanceList SubsList;
        boost::archive::binary_iarchive iar(plik);  //// (E)
        iar >> SubsList;    //// (D)
        plik.close();    //// (C)
    }
}

po pierwsze, popełniłeś u siebie
ar & v.itsElasticity[6][6]; //// (A)
powoduje to zapisanie dosc kuriozalnego pojedynczego "elementu" tablicy, Ty zas chciales zapisac tablice:
ar & v.itsElasticity; //// (A)

po drugie, linijki (B) oraz (C) w zasadzie nie powinny sie tam byly znalezc, acz nie szkodza one zwykle nikomu. w C++ destruktory strumieni powoduja ich zamkniecie, wiec wystarczy ze "fout" oraz "plik" wyjda poza 'scope' i zamkna sie same. Co wiecej, tyczy sie to rowniez OAR i IAR - siłą rzeczy sa tworzone PO strumieniach, wiec ich destruktory odpala sie najpierw, a dopiero potem destr. strumieni. W momencie gdy Ty najpierw recznie odpalasz close na strumieniu, teoretycznie odcinasz OAR'owi mozliwosc zapisania sobie czegos na koncu pliku po juz zakonczonej serializacji. On tego nie robi, przynajmniej w tej wersji, ale generalnie, jesli juz uzywamy RAII, to uzywajmy jej zamiast odcinac komus gałąź na ktorej siedzi:)

szczerze mowiac, nie wiem skad wzial Ci sie blad wtedy, powyzszy kod dziala u mnie poprawnie. Byc moze wpadka w miejscu (A) powodowala u Ciebie pechowe uszkodzenie pamieci - ostatecznie serializer posłusznie wpisywał w element '6-6' jakąś tam wartosc z pliku.

inna rzecz, ze jezeli Twoj oryginalny program wygladal lekko inaczej, to tez sie mogl sypac, jednak nie w miejscu 'D', tylko w 'E'. Np. jezeli po zapisaniu OAR'a jakos wskakiwales do bloku czytajacego plik, np. ot tak dla sprawdzenia, to z linijki E moglbys otrzymywac wyjatek 'invalid signature' lub cos podobnego, bioracy sie stad, ze ifstream z linii F caly czas sadzi ze plik nie istnieje/ał i trzeba tego ifstreama szturchnac..

sadze, ze jednak miales pecha z powodu linii (A).
nie rezygnuj z boost::serialization, przyda Ci sie bardzo jak bedziesz mial bardziej skomplikowane grafy do zrzucenia do pliku:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1