Zapis/odczyt struktury do/z pliku binarnego

0

Cześć, mam problem z zapisem struktury do pliku binarnego.

Stworzyłem sobie taki kod:

int myL = 1;

struct pData
{
	int currentL;
};

pData myData;

// -- Odczyt -- //
// .. otwarcie pliku juz po drodze
file.read((char*)&myData, sizeof(pData));

myData.currentL = myL; // To jest dobrze?

// -- Zapis -- //
file.write((char*)&myData, sizeof(pData));

Problem w tym, że to w ogóle nie działa, ale dlaczego? Kierowałem się poradnikami i jest tak samo, ale nie działa.

0

Zapisuj poszczególne pola struktury.

#include<iostream>
#include<fstream>
using namespace std;

struct test {
	int integer;
	float floating;
};

void save(const char* path, const test& source) {
	fstream file(path, ios::out | ios::binary);
	if (file.is_open()) {
		file.write((char*)&source.integer, sizeof(source.integer));
		file.write((char*)&source.floating, sizeof(source.floating));
		file.close();
	}
}

void load(const char* path, test& destination) {
	fstream file(path, ios::in | ios::binary);
	if (file.is_open()) {
		file.read((char*)&destination.integer, sizeof(destination.integer));
		file.read((char*)&destination.floating, sizeof(destination.floating));
		file.close();
	}
}

int main() {
	test testData;
	testData.integer = 12;
	testData.floating = 1.4f;
	save("test.bin", testData);

	test loaded;
	load("test.bin", loaded);
	cout << "Int: " << loaded.integer << " Float: " << loaded.floating << endl;	
	return 0;
}
0
TurboMen napisał(a):

Problem w tym, że to w ogóle nie działa, ale dlaczego? Kierowałem się poradnikami i jest tak samo, ale nie działa.
Z tego co opisałeś w komentarzach to dobrze ci to działa. Przy zapisie binarnym który stosujesz, plik nie jest czytelny dla zwykłego użytkownika.
Weź napisz coś w wordzie po czym zapisz plik i spróbuj otworzyć ten plik notatnikiem, to jest właśnie zapis binarny.

0

Powyższy kod daje taki sam rezultat jak mój.

Oprócz tego problemu, mam jeszcze pytanie dot. tego samego kodu: Jak sprawdzać dane w strukturze w warunku (np. if)?
Wystarczy: if(pData.currentL == myL) pData.currentL = 0;?

@_13th_Dragon: O to mi chodzi, plik ma się stać nieczytelny, a jednocześnie kod sobie odtworzy stamtąd dane - plik z zapisem danych gry :P

@grzesiek51114, mój kod jest aktualnie taki:

struct s_pData
{
	int currentL;
};

s_pData pData;

void loadSettings()
{
	// -- First from file -- //
	ifstream file("game.dat", ios::binary);

	if (file.good())
	{
		// -- Language -- //
		file.read((char*)&pData.currentL, sizeof(pData.currentL));

		file.close();
	}
}

void saveSettings()
{
	ofstream file("game.dat", ios::binary);

	if (file.good())
	{
		// -- Language -- //
		file.write((char*)&pData.currentL, sizeof(pData.currentL));

		file.close();
	}
}

Dane zmieniam tak:

pData.currentL = 1;
pData.currentL = 5;

itd..

0

Pokaż cały kod, który spłodziłeś. Cały. Razem z mainem itp.

Tak na marginesie to jeżeli z obiektem std::fstream nie robisz nic więcej to nie musisz go zamykać (file.close();) bo jest on napisany zgodnie z zasadami RAII (https://pl.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization). Czyli w skrócie - std::fstream sam zadba, żeby przy niszczeniu obiektu plik został zamknięty.

0
struct s_pData
{
    int currentL;
};
 
s_pData pData;
 
void loadSettings()
{
    // -- First from file -- //
    ifstream file("game.dat", ios::binary);
 
    if (file.good())
    {
        // -- Language -- //
        file.read((char*)&pData.currentL, sizeof(pData.currentL));
        // Poprzednia wersja: file.read((char*)&pData, sizeof(pData));
 
        file.close();
    }
}
 
void saveSettings()
{
    ofstream file("game.dat", ios::binary);
 
    if (file.good())
    {
        // -- Language -- //
        file.write((char*)&pData.currentL, sizeof(pData.currentL));
        // Poprzednia wersja: file.write((char*)&pData, sizeof(pData));
 
        file.close();
    }
}

int main()
{
    loadSettings();

    pData.currentL = 2;

    saveSettings();

     return 0;
}
0

Ok, a teraz wyjaśnij jakiego oczekiwałeś rezultatu, a jaki otrzymałeś? Możesz też załączyć ten plik binarny.

0

Gdy zrobiłem taki kod:

int *myL = 1;

file.write((char*)&myL, sizeof(myL));

...

file.read((char*)&myL, sizeof(myL));

To wszystko jest w porządku, kod poprawnie odczytuje zapisane dane.

0

Przecież to działa:

int main()
{
	loadSettings();
	cout << pData.currentL << endl;
	pData.currentL = 88;
	saveSettings();
	return 0;
}

Program ładnie wczytuje wartość zapisaną podczas poprzedniego uruchomienia aplikacji. http://pastebin.com/HreKDcDT

PS: Zapisanie binarnie danych do pliku wcale nie oznacza, że użytkownik nie będzie mógł ich modyfikować vide hexa edytor.

1

Wystarczy tyle:

#include <fstream>
#include <iostream>
using namespace std;

struct
  {
   int currentL;
   double cos;
  }
  pData = 
  {  
   0, // domyślna wartość dla currentL
   666.13, // domyślna wartość dla cos
  };
 
void loadSettings()
  {
   ifstream file("game.dat",ios::binary);
   file.read((char*)&pData,sizeof(pData));
  }
 
void saveSettings()
  {
   ofstream file("game.dat",ios::binary);
   file.write((char*)&pData,sizeof(pData));
  }

int main()
  {
   cout<<pData.currentL<<' '<<pData.cos<<endl; // musi być domyślne 0 666.13
   loadSettings();
   cout<<pData.currentL<<' '<<pData.cos<<endl; // muszą być ostatnie wartości
   pData.currentL+=2;
   pData.cos*=2;
   cout<<pData.currentL<<' '<<pData.cos<<endl; // te nowe, zmienione dane
   saveSettings(); 
   return 0;
  }

zauważ że jednym ciurkiem zapisujesz wszystkie wartości na raz.

1

A zakład o piątaka, że wszystko działa tak jak chcesz? (:

int main()
{
	
	//ustawienie pl
    pData.currentL = 1;
 
 	//zapisanie danych do pliku
    saveSettings();
    
    //to, żeby bylo widac roznice
    pData.currentL = 2;
    
    std::cout<<pData.currentL<<endl;
    
    loadSettings();
 
    std::cout<<pData.currentL<<endl;
 
     return 0;
}

Zrób takiego maina i zobacz na wyniki

0

Zamień sobie save z load i przekonaj się, że wszystko naprawdę jest ok.

int main()
{
	pData.currentL = 15;
	saveSettings();
	loadSettings();
	cout << pData.currentL << endl;
	return 0;
}

Przecież nie zobaczysz zmian w programie jeżeli najpierw odczytujesz wartości, a później je zapisujesz i zamykasz aplikacje. Jak chcesz zobaczyć zmienione zapisane dane kiedy zaraz po zapisie zamykasz program. Dopiero podczas drugiego uruchomienia będziesz to widział.

0

No nie działa, żadne z waszych rozwiązań.

Plik wyjściowy ma zawartość (dla 1): http://scr.hu/5icj/vhldo

WTF?

2

Przecież te wszystkie kody działają od pierwszego posta. Od zawsze działały.

Plik binarny należy otworzyć hexedytorem a nie notatnikiem. Ile razy można to pisać?

Jeżeli nadal coś nie działa pokaż cały oryginalny kod a nie jakiś przykładowy fragment.

0

Otworzyłem, dla zapisanej jedynki jest okej.

Teraz zapiszcie sobie tymi kodami dwójkę, plik będzie pusty, a ja mam związane ręce:
http://scr.hu/5icj/rf53g

EDIT: Dobra, all działa, dziwne, że kod pusty plik jednak odczytuje lel. Dziękuję wszystkim za pomoc.

Teraz pytanie: Jak zakodować zapisane dane, aby nikt ich nie odczytał, ewentualnie zabezpieczyć przed edycją (np. po edycji save się nie załaduje)

2

Dobra, all działa, dziwne, że kod pusty plik jednak odczytuje lel. Dziękuję wszystkim za pomoc.

Ten plik nie jest pusty tylko Ty nie rozumiesz o co chodzi w zapisie binarnym.

Teraz pytanie: Jak zakodować zapisane dane, aby nikt ich nie odczytał

Zaszyfruj.

1
TurboMen napisał(a):

Teraz zapiszcie sobie tymi kodami dwójkę, plik będzie pusty, a ja mam związane ręce:
http://scr.hu/5icj/rf53g
Ile razy ci trzeba powtórzyć aby zrozumiałeś, plik binarny nie możesz oglądać notatnikiem!
Jest tam zapisana ta dwójka.

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