2010-12-21 4 views
2

파일에 저장해야하는 두 가지 구조체가 있습니다. 구조체를 파싱하지 않고 텍스트 파일로 쓰지 않고도 파일로 가져올 수있는 좋은 방법을 찾을 수 없습니다. 이는 내가 원하는 것보다 훨씬 효율적이지 않습니다. 무엇이 가장 원시적 인 구조체를 파일로 가져 오는 가장 간단한 방법은 무엇입니까? 구조체가 아래에 있습니다쉽게 다시로드 할 수 있도록 구조체를 파일에 저장하는 방법은 무엇입니까?

구조체를 파일에 쓰려고 시도했지만 아주 잘 작동하지 않습니다. 실행 후 파일 크기는 4.7kb에 불과하지만 그보다 훨씬 커야합니다.

sector s; 
object o; 
s.id = 1; 
s.neighbors = {2, 3, 4, 5}; 
o.id = 1; o.x = 2.0f; o.y = 3.0f; o.type = 4; o.flags = 6; 
for(int i = 0; i < 65536; i++) 
{ 
    s.objects.push_back(o); 
    o.id += 1; o.x += 1.0f; o.y += 1.0f; o.type += 1; o.flags += 1; 
} 

ofstream os("world.dat", ios::binary|ios::out); 
s.objects.resize(s.objects.size()); 
int size = s.objects.size() * sizeof(object); 
os.write((char*)&size, sizeof(int)); 
os.write((char*)&s, size); 
os.close(); 

의견이 있으십니까?

+0

메모리를 디스크에 직접 저장하는 출력을 시도 했습니까? 예를 들어'memcpy'를'& o'에서'byte' 배열로 바꾼 후 디스크에 이진 데이터로 저장합니다 – Itsik

+0

4.7kb라면? 그것이 유효한지보기 위해 디스크에서 다시 읽으려고 했습니까? 그렇다면 설정되어 있습니다. –

+0

@Itsik은 기본적으로 메모리에있는 diff 위치로 데이터를 복사하지 않고 그가하고있는 것입니다. –

답변

3

원시 바이트 입출력을 사용하여 벡터를 포함하는 구조체를 작성할 수 없습니다. 벡터 클래스는 구조체가 아닌 힙에 데이터를 저장하는 작은 데이터 구조입니다. 이는 구조체가 보유 할 객체의 수를 미리 "알기"때문에 불가능하기 때문입니다.

당신은 따라서 벡터의 내용을 작성할 수 있습니다

os.write((const char*)&s.id, sizeof(s.id)); 
os.write((const char*)&s.neighbors, sizeof(s.neighbors)); 
os.write((const char*)&s.objects[0], size); 

파일이 단지 4.7 킬로바이트로 끝나는 이유에 관해서는, 나도 몰라. size을 인쇄하여 기록되는 데이터의 양을 확인하십시오. 위의 변경 후 코드를 확인하고 작동합니다.

s.objects.resize(s.objects.size());도 필요하지 않습니다. 벡터 크기를 자체 크기로 조정하면 중복됩니다.

작은 변태에 유의하십시오. sizeof (object) == 16 위의 구조체 (2 + 4 + 4 + 2 + 1 == 13)보다 더 많이 필요합니다. 컴파일러는 일반적으로 크기가 2 N 프리미티브의 각 구조체의 내부 구멍과 벡터 구조체 사이 결과 2 N -byte 경계에 정렬되는 것을 보장하기 위해 패딩을 추가한다.

결과적으로 파일에 여분의 바이트를 쓰고 있으며 일부는 랜덤 노이즈입니다. 비 - 디버그 빌드에서, 그 구멍은 아무것도 채워지지 않으므로, 목적을 위해 할당되기 전에 그 메모리 위치에 있던 쓰레기를 그냥 포함합니다. 따라서 프로그램을 두 번 실행하면 두 파일이 동일하지 않을 가능성이 있습니다.

+0

그래서 벡터에서 데이터를 파일로 개별적으로 가져 오거나 해당 구조체 내에 객체를 저장하는 다른 방법을 찾아야합니다. – Bocochoco

+0

예, 코드가 거의 있습니다. 제 수정 된 답변을보십시오. –

+0

어리석은 실수를 바로 잡기 위해 내 대답을 다시 수정했습니다. –

0

방금 ​​솔루션을 찾은 것 같습니다. 객체의 수는 상수이기 때문에 벡터 사용은 불필요합니다. vector<object> objectsobject objects[256][256]으로 바꿨는데, 이는 현재 코드로 파일에 올바르게 기록됩니다. 나는 또한 x, y 좌표 시스템에 찬성하여 이드와 이웃하는 이드에 의해 다른 섹터에 상대적으로 한 섹터의 위치를 ​​추적하는 것을 포기했다. 추적하기가 더 쉬워야합니다. 왜 내가 항상 물건을 과도하게 복제하고 단순화하는지 알았 으면 좋겠어.

struct object 
{ 
    unsigned short id; 
    float x; 
    float y; 
    unsigned short type; 
    unsigned char flags; 
}; 
struct sector 
{ 
    unsigned long x; 
    unsigned long y; 
    object objects[256][256]; 
}; 
sector s; 
object o; 

s.x = 1; s.y = 1; 
o.id = 1; o.x = 2.0f; o.y = 3.0f; o.type = 4; o.flags = 6; 
for(int x = 0; x < 256; x++) 
{ 
    for(int y = 0; y < 256; y++) 
    { 
     s.objects[x][y] = o; 
     o.id += 1; o.x += 1.0f; o.y += 1.0f; o.type += 1; o.flags += 1; 
    } 
} 

ofstream os("world.dat", ios::binary|ios::out); 
int size = sizeof(sector); 
os.write((char*)&s, size); 
os.close(); 

이것은 올바르게 작동하고있다. 나는 내가하고있는 일이 2 차원지도를 만드는 것이라고 생각한다. 각 노드는 2 차원지도를 가지고있다. 아마도 더 좋은 방법이있을 것입니다.

+0

예, 작동합니다. 그래도 최근 답변에는 작은주의 사항이 있습니다. –

+0

@Marcelo Cantos, 나는 그것이 출력물을 채웠다는 것을 알았다. 그러나 나는 그것이 0을 사용한다고 생각했다. 지금 다른 것. .. 예! – Bocochoco

4

boost::serialization과 같은 직렬화 라이브러리를 사용할 수있는 것처럼 들립니다. 이것은 STL 컨테이너에 대한 지원을 상자에 넣었으므로 예제에서 구조체를 지원하는 것이 매우 간단해야합니다.

0

fread()fwrite()을 보았습니까?이 파일에 대한 인간 readablity 및 객체와 부문이 필요하지 않은 경우 모두 포드이며, 다음 이런 종류의 당신을 위해 작동합니다 :

일반적으로
object o; 
FILE * fh = ...; 
... 
fwrite(&o, sizeof(o), 1, fh); 

fread(&o, sizeof(o), 1, fh); 

나는 C 지향 코딩 이런 종류의 권하고 싶지 않다 , 때로는 오래된 방법이 여전히 가장 단순합니다.

이 코드는 object의 섹터 배열이 일정한 크기 여야 함을주의하십시오.

0

4.7K만이 파일에 저장되는 이유를 알고 싶다면 사용중인 OS와 사용중인 C++ 컴파일러를 말해야합니다. 's'가 스택에 있기 때문에 파일에 '&'을 쓰도록 선택했을 때 스택의 4.7K 만 사용되었다는 합리적인 가정이됩니다. Windows에서 환경 블록은 3.8K의 스택 공간을 차지합니다. 따라서 Windows에서 응용 프로그램은 '&'에 write()를 호출하기로 선택한 지점에서 0.9k의 추가 스택 공간 (환경 블록 이후)을 사용했으며 스택이 아래쪽으로 커지기 때문에 C++ 구현 스택이 시작되는 지점까지만 write()를 명예롭게 해주는 것을 선택했다. 즉, '&'위의 4.7K이다.

0

라이브러리를 사용하지 않으려면 구조가 POD 여야합니다. 그런 다음 전체 구조를 이진 파일에 저장할 수 있습니다. 그렇지 않으면 힙에 데이터가 할당 될 수 있습니다.

관련 문제