ofstream, ifstream

#include <fstream> 사용.

기본 파일 입출력 클래스. 

ios_base::in/out/binary/ate(파일포인터를 끝부분으로)/app(파일의 끝에 항상 기록)/trunc( 있던 내용 모두 삭제)

struct Person {
    string name;
    int age;
    char item[2];
    }
};


int main() {
    Person person;
    person.name = "John";
    person.age = 30;
    person.item[0] = 'A';
    person.item[1] = 'B';

    // 구조체 직렬화 저장 (바이너리)
    ofstream file("person_data.bin", ios::binary);
    if (!file.is_open()) {
        cout << "Failed to open file for writing." << endl;
        return 1;
    }

    file.write(reinterpret_cast<char*>(&person), sizeof(person));	//파일 쓰기
    file.close();

    cout << "Data written to file." << endl;

    // 구조체 역직렬화 읽기
    ifstream readFile("person_data.bin", ios::binary);
    if (!readFile.is_open()) {
        cerr << "Failed to open file for reading." << endl;
        return 1;
    }

    Person readPerson;
    readFile.read(reinterpret_cast<char*>(&readPerson), sizeof(readPerson));

    cout << "Name: " << readPerson.name << endl;
    cout << "Age: " << readPerson.age << endl;
    cout << "Item: " << readPerson.item[0] << readPerson.item[1] << endl;

    readFile.close();

    return 0;
}

 

 

Boost.Serialization

객체를 Binary파일로 저장하거나 통신을 통해 데이터를 다른 곳으로 전달 해야 될 경우, Primitive Type(숫자, enum, bool) 변수만 전달 될 수 있다.

객체를 온전히 전달하기 위해선 Serialization(직렬화)해야만 stream으로 전달 할 수 있다.

 

이것을 해주는 것이 C++에는 Boost라는 라이브러리에서 지원해준다. 별도 설치가 필요하다.

 

Boost의 객체 직렬화는 아카이브(Archive) 라는 클래스로 수행한다. 각각의 헤더를 포함해서 쓸 수 있다.

ex) #include <boost/archive/text_oarchive.hpp>

//텍스트 
boost::archive::text_oarchive	//saving
boost::archive::text_iarchive	//loading

boost::archive::text_woarchive
boost::archive::text_wiarchive

//xml
boost::archive::xml_oarchive
boost::archive::xml_iarchive

boost::archive::xml_woarchive
boost::archive::xml_wiarchive

//바이너리 
boost::archive::binary_oarchive
boost::archive::binary_iarchive

 

직렬화 대상 Class템플릿 함수 serialize()를 정의해야하고, 이를 직렬화 할때 사용하는 boost::serialization::access 클래스가 대상 Class에 접근할 수 있도록 friend 선언을 해주어야 한다.

#include <boost/serialization/access.hpp>

class Target
{
    string name;
    int age;
    
    friend class boost::serialization::access;
    
    template<typename Archive>
    void serialize(Archive& ar, const unsinged int version);
};

template<typename Archive>
void Tearget::serialize(Archive& ar, const unsinged int version)
{
    // 모든 멤버 변수를 Archive ar의 & 연산자로 전달
    ar & name;
    ar & age;
}

 

직렬화, 역직렬화 수행 예제)

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

//[직렬화 수행]
Target obj;

ostringstream oss;		//직렬화 하여 저장될 곳. 파일도 될 수 있음(ofsteram)

boost::archive::text_oarchive oarch(oss);		//직렬화 수행 아카이브에 스트림 등록

oarch << obj;	//객체를 아카이브에 입력으로 전달


//[역직렬화 수행]
Target loadData;

istringstream iss(oss.str());		//역직렬화 대상. 파일도 될 수 있음(ifstream)

boost::archive::text_iarchive iarch(iss);		//역직렬화 수행 아카이브에 스트림 등록

iarch >> loadData;	//아카이브에서 부터 객체 데이터 추출

 

 

proto3(Google Protocol Buffers)

boost::serialization은 데이터 저장/로드 용도로 적합하다.

proto3데이터 교환(통신)용으로 적합하다. (다양한 언어와 플랫폼 간)

프로토콜 버퍼 스키마를 정의하고 컴파일하여 사용하므로, 추가적인 스키마 정의(.proto)가 필요하다.

 

 

'c, c++ 리마인드' 카테고리의 다른 글

c++ pair, lower_bound/upper_bound 유의 사항  (0) 2023.09.24
ANSI, UNICODE, UTF-x  (0) 2023.09.05
c++ stringstream  (0) 2023.08.27
c++ cast  (0) 2023.08.26
struct, class 크기 결정  (0) 2023.08.25

+ Recent posts