2011-01-11 5 views
2

C++에서 압축 된 데이터 형식을 사용하고 메모리에서 저장하거나 파일에서로드하면 메모리의 비트를 복사하여 넣거나 꺼내기 만하면됩니다.메모리 기반 데이터 형식의 변경 관리

그러나 명백한 단점은 데이터에 요소를 추가/제거해야하는 경우 일종의 지저분 해집니다. 또한 버전 관리에 문제가 있습니다. 버전 A의 데이터를 사용하는 프로그램을 배포 한 다음 다음 날에 B 버전을 만든 다음 버전 C를 나중에 작성한다고 가정하십시오.

이 문제는 다음을 사용하여 해결할 수 있다고 생각합니다. xml이나 json과 같은 것. 그러나 기술적 인 이유 때문에 그렇게 할 수 없다고 가정 해보십시오.

떨어져 경우 등 (꽤 추한 것, 내가 상상하는 것) 경우

+0

* 데이터 * 또는 * 유형 *의 다른 버전을 의미합니까? – Beta

+0

다른 버전의 데이터. 실제로 omnitarius가 프로토콜 버퍼를 사용한다고 생각하는 것과 정확히 일치합니다. – kamziro

답변

2

'기술적 이유'가 무엇인지 모르지만 속도 나 데이터 크기가 관련되어 있다면 해결책으로 Protocol Buffers을 제안 할 수 있습니다. 버전 관리를 처리하도록 명시 적으로 설계되었습니다. 단순히 구조체를 덤프하는 것보다 약간 느리고 약간 큽니다. 그러나 약간만 포팅하면 훨씬 더 이식성이 뛰어나고 더 나은 버전 관리가 가능해집니다.

+0

음, 그래, 그거 좋은데. 나는 그걸 들여다 볼지도 모른다. 고마워! – kamziro

2

(I 잘 기억한다면) 3DSMAX에서 오는 아이디어를 다른 수 있도록 할 필요가, 이렇게하는 가장 좋은 방법은 무엇입니까 : 파일을 청크로 나눕니다. 각 청크에는 헤더 (길이가 길어질 수 있음)와 길이가입니다. 읽을 때 머리말을 모르는 경우 len을 알면 다음 글자로 건너 뜁니다. 이 프로세스는 각 청크 내에서 재귀 적으로 적용되며 이전 버전과의 호환성을 보장합니다.

+0

이것은 프로토콜 버퍼가하는 것처럼 들립니다. :-) – Omnifarious

+0

흥미 롭다. 실제로 CSHARP 언어로 protobuff을 구현했지만, 너무 많이 보지 않았다;) –

0

이것은 이 해킹하는 방식입니다. 그것은 "해킹"접근이지만 더 정교해질 수 있도록 확장 될 수 있습니다. 당신 것, 이기종 블록

f.fileversion = read(sizeof(f.fileversion)) 
f.offsetlen = read(sizeof(f.offsetlen)) 
f.numblocks = read(sizeof(f.numblocks)) 
for i in f.numblocks 
    f.blocks[i] = read(f.offsetlen) 

을 -

struct file 
{ 
int32 fileversion; //different parsers, one for each file version 
int offsetlen;  //length of blocks 
int numblocks;  //number of blocks 
int* fileoffsets; //this array has internal offsets, corresponding to blocks 
block* blocklist;  //blocks. 
}; 

struct block 
{ 
    //stuff here of a fixed length 
}; 

고정 된 크기의 블록을 가진 파일을 작성하려면, 알고리즘은 다음과 같이 될 것이다 -

write(f.fileversion) 
write(f.offsetlen) 
write(f.numblocks) 
for i in f.blocklist 
    write(f.blocklist[i]) 

및 읽기 읽는 동안 오프셋을 추적해야합니다.

0

"열 기반"방식으로 이동하면 원하는대로 필드를 추가 할 수 있습니다.

옛날 방식으로

원래 구조체 :

struct Person { 
    string name; 
    int age; 
    string address; // now must rewrite files on disk 
}; 

새롭고 개선 된 방법 :

namespace People { 
    vector<string> name; // first file 
    vector<int> age;  // second file 
} 

새로운 방식에 추가 : 옛날 방식으로

struct Person { 
    string name; 
    int age; 
}; 

vector<Person> People; // single file for all fields 

추가 필드

namespace People { 
    vector<string> name; 
    vector<int> age; 
    vector<string> address; // add a third file and leave other two alone 
} 

요지는 각 필드가 자체 파일이라는 것입니다. 추가 혜택은 사용자가 원하는 필드를 읽고 쓰는 것만으로 버전 관리가 쉬워진다는 것입니다.

+1

사용자로서, 나는 이것을 싫어할 것이다. 간단한 백업을하기 위해 파일의 crapload를 복사하는 것은 매우 짜증나는 일입니다. –

+0

@Billy * 간단한 백업을하기 위해 파일의 crapload를 복사해야하는 것은 매우 짜증나는 일입니다. * OP는 어떻게 다르게 진행 되었습니까? – chrisaycock

+0

@chrisaycock : OP가 단일 파일을 사용 중입니다. –

0

내 작업에서이 문제를 처리합니다. 그것은 최선은 아니지만 몇 가지 당신은 할 수 있습니다 :

  • 가 첫 번째 필드는 "버전"와 두 번째 필드 인 "길이"되는 모든 파일에 헤더를 추가합니다. 로드시에는 이전 버전을 적절하게 처리 할 수 ​​있습니다.

  • "할 수 있으면 데이터 필드를 삭제하지 말고 항상 파일 끝에 필드를 추가하십시오."규칙을 만드십시오. 이렇게하면 로딩 코드가 사용 가능한 데이터를 struct로 읽어 들이고 파일에없는 마지막 필드를 초기화 한 채로 오래되고 짧은 버전의 파일을로드 할 수 있습니다. 구조체의 배열을 가질 때이 부분이 떨어져서, 그 시점에서 수동으로 데이터를로드해야합니다.